xref: /aosp_15_r20/external/google-fruit/include/fruit/impl/meta/component.h (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1*a65addddSAndroid Build Coastguard Worker /*
2*a65addddSAndroid Build Coastguard Worker  * Copyright 2014 Google Inc. All rights reserved.
3*a65addddSAndroid Build Coastguard Worker  *
4*a65addddSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker  *
8*a65addddSAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker  *
10*a65addddSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker  * limitations under the License.
15*a65addddSAndroid Build Coastguard Worker  */
16*a65addddSAndroid Build Coastguard Worker 
17*a65addddSAndroid Build Coastguard Worker #ifndef FRUIT_META_COMPONENT_H
18*a65addddSAndroid Build Coastguard Worker #define FRUIT_META_COMPONENT_H
19*a65addddSAndroid Build Coastguard Worker 
20*a65addddSAndroid Build Coastguard Worker #include <fruit/fruit_forward_decls.h>
21*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/fruit_internal_forward_decls.h>
22*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/injection_debug_errors.h>
23*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/algos.h>
24*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/errors.h>
25*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/list.h>
26*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/map.h>
27*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/metaprogramming.h>
28*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/numeric_operations.h>
29*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/proof_trees.h>
30*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/set.h>
31*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/signatures.h>
32*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/wrappers.h>
33*a65addddSAndroid Build Coastguard Worker 
34*a65addddSAndroid Build Coastguard Worker #include <memory>
35*a65addddSAndroid Build Coastguard Worker #include <type_traits>
36*a65addddSAndroid Build Coastguard Worker 
37*a65addddSAndroid Build Coastguard Worker namespace fruit {
38*a65addddSAndroid Build Coastguard Worker namespace impl {
39*a65addddSAndroid Build Coastguard Worker namespace meta {
40*a65addddSAndroid Build Coastguard Worker 
41*a65addddSAndroid Build Coastguard Worker //********************************************************************************************************************************
42*a65addddSAndroid Build Coastguard Worker // Part 1: Simple type functors (no ConsComp involved).
43*a65addddSAndroid Build Coastguard Worker //********************************************************************************************************************************
44*a65addddSAndroid Build Coastguard Worker 
45*a65addddSAndroid Build Coastguard Worker // Given a type T, returns the class that should be injected to ensure that T is provided at runtime (if any).
46*a65addddSAndroid Build Coastguard Worker struct GetClassForType {
47*a65addddSAndroid Build Coastguard Worker   // General case, if none of the following apply.
48*a65addddSAndroid Build Coastguard Worker   // When adding a specialization here, make sure that the ComponentStorage
49*a65addddSAndroid Build Coastguard Worker   // can actually get<> the specified type when the class was registered.
50*a65addddSAndroid Build Coastguard Worker   template <typename T>
51*a65addddSAndroid Build Coastguard Worker   struct apply;
52*a65addddSAndroid Build Coastguard Worker 
53*a65addddSAndroid Build Coastguard Worker   template <typename T>
54*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T>> {
55*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
56*a65addddSAndroid Build Coastguard Worker   };
57*a65addddSAndroid Build Coastguard Worker 
58*a65addddSAndroid Build Coastguard Worker   template <typename T>
59*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T>> {
60*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
61*a65addddSAndroid Build Coastguard Worker   };
62*a65addddSAndroid Build Coastguard Worker 
63*a65addddSAndroid Build Coastguard Worker   template <typename T>
64*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T*>> {
65*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
66*a65addddSAndroid Build Coastguard Worker   };
67*a65addddSAndroid Build Coastguard Worker 
68*a65addddSAndroid Build Coastguard Worker   template <typename T>
69*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T&>> {
70*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
71*a65addddSAndroid Build Coastguard Worker   };
72*a65addddSAndroid Build Coastguard Worker 
73*a65addddSAndroid Build Coastguard Worker   template <typename T>
74*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T*>> {
75*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
76*a65addddSAndroid Build Coastguard Worker   };
77*a65addddSAndroid Build Coastguard Worker 
78*a65addddSAndroid Build Coastguard Worker   template <typename T>
79*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T&>> {
80*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
81*a65addddSAndroid Build Coastguard Worker   };
82*a65addddSAndroid Build Coastguard Worker 
83*a65addddSAndroid Build Coastguard Worker   template <typename T>
84*a65addddSAndroid Build Coastguard Worker   struct apply<Type<std::shared_ptr<T>>> {
85*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
86*a65addddSAndroid Build Coastguard Worker   };
87*a65addddSAndroid Build Coastguard Worker 
88*a65addddSAndroid Build Coastguard Worker   template <typename T>
89*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Assisted<T>>> {
90*a65addddSAndroid Build Coastguard Worker     using type = None;
91*a65addddSAndroid Build Coastguard Worker   };
92*a65addddSAndroid Build Coastguard Worker 
93*a65addddSAndroid Build Coastguard Worker   template <typename T>
94*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Provider<T>>> {
95*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
96*a65addddSAndroid Build Coastguard Worker   };
97*a65addddSAndroid Build Coastguard Worker 
98*a65addddSAndroid Build Coastguard Worker   template <typename T>
99*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Provider<const T>>> {
100*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
101*a65addddSAndroid Build Coastguard Worker   };
102*a65addddSAndroid Build Coastguard Worker 
103*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T>
104*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, T>>> {
105*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
106*a65addddSAndroid Build Coastguard Worker   };
107*a65addddSAndroid Build Coastguard Worker };
108*a65addddSAndroid Build Coastguard Worker 
109*a65addddSAndroid Build Coastguard Worker struct GetClassForTypeVector {
110*a65addddSAndroid Build Coastguard Worker   template <typename V>
111*a65addddSAndroid Build Coastguard Worker   struct apply {
112*a65addddSAndroid Build Coastguard Worker     using type = TransformVector(V, GetClassForType);
113*a65addddSAndroid Build Coastguard Worker   };
114*a65addddSAndroid Build Coastguard Worker };
115*a65addddSAndroid Build Coastguard Worker 
116*a65addddSAndroid Build Coastguard Worker // Given a type T, returns the type in the injection graph that corresponds to T.
117*a65addddSAndroid Build Coastguard Worker struct NormalizeType {
118*a65addddSAndroid Build Coastguard Worker   // When adding a specialization here, make sure that the ComponentStorage
119*a65addddSAndroid Build Coastguard Worker   // can actually get<> the specified type when the class was registered.
120*a65addddSAndroid Build Coastguard Worker   template <typename T>
121*a65addddSAndroid Build Coastguard Worker   struct apply;
122*a65addddSAndroid Build Coastguard Worker 
123*a65addddSAndroid Build Coastguard Worker   template <typename T>
124*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T>> {
125*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
126*a65addddSAndroid Build Coastguard Worker   };
127*a65addddSAndroid Build Coastguard Worker 
128*a65addddSAndroid Build Coastguard Worker   template <typename T>
129*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T>> {
130*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
131*a65addddSAndroid Build Coastguard Worker   };
132*a65addddSAndroid Build Coastguard Worker 
133*a65addddSAndroid Build Coastguard Worker   template <typename T>
134*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T*>> {
135*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
136*a65addddSAndroid Build Coastguard Worker   };
137*a65addddSAndroid Build Coastguard Worker 
138*a65addddSAndroid Build Coastguard Worker   template <typename T>
139*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T&>> {
140*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
141*a65addddSAndroid Build Coastguard Worker   };
142*a65addddSAndroid Build Coastguard Worker 
143*a65addddSAndroid Build Coastguard Worker   template <typename T>
144*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T*>> {
145*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
146*a65addddSAndroid Build Coastguard Worker   };
147*a65addddSAndroid Build Coastguard Worker 
148*a65addddSAndroid Build Coastguard Worker   template <typename T>
149*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T&>> {
150*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
151*a65addddSAndroid Build Coastguard Worker   };
152*a65addddSAndroid Build Coastguard Worker 
153*a65addddSAndroid Build Coastguard Worker   template <typename T>
154*a65addddSAndroid Build Coastguard Worker   struct apply<Type<std::shared_ptr<T>>> {
155*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
156*a65addddSAndroid Build Coastguard Worker   };
157*a65addddSAndroid Build Coastguard Worker 
158*a65addddSAndroid Build Coastguard Worker   template <typename T>
159*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Assisted<T>>> {
160*a65addddSAndroid Build Coastguard Worker     using type = None;
161*a65addddSAndroid Build Coastguard Worker   };
162*a65addddSAndroid Build Coastguard Worker 
163*a65addddSAndroid Build Coastguard Worker   template <typename T>
164*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Provider<T>>> {
165*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
166*a65addddSAndroid Build Coastguard Worker   };
167*a65addddSAndroid Build Coastguard Worker 
168*a65addddSAndroid Build Coastguard Worker   template <typename T>
169*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Provider<const T>>> {
170*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
171*a65addddSAndroid Build Coastguard Worker   };
172*a65addddSAndroid Build Coastguard Worker 
173*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T>
174*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, T>>> {
175*a65addddSAndroid Build Coastguard Worker     using type = Type<fruit::Annotated<Annotation, UnwrapType<Eval<NormalizeType(Type<T>)>>>>;
176*a65addddSAndroid Build Coastguard Worker   };
177*a65addddSAndroid Build Coastguard Worker };
178*a65addddSAndroid Build Coastguard Worker 
179*a65addddSAndroid Build Coastguard Worker struct NormalizeUntilStable {
180*a65addddSAndroid Build Coastguard Worker   template <typename T>
181*a65addddSAndroid Build Coastguard Worker   struct apply {
182*a65addddSAndroid Build Coastguard Worker     using type = If(IsSame(NormalizeType(T), T), T, NormalizeUntilStable(NormalizeType(T)));
183*a65addddSAndroid Build Coastguard Worker   };
184*a65addddSAndroid Build Coastguard Worker };
185*a65addddSAndroid Build Coastguard Worker 
186*a65addddSAndroid Build Coastguard Worker struct NormalizeTypeVector {
187*a65addddSAndroid Build Coastguard Worker   template <typename V>
188*a65addddSAndroid Build Coastguard Worker   struct apply {
189*a65addddSAndroid Build Coastguard Worker     using type = TransformVector(V, NormalizeType);
190*a65addddSAndroid Build Coastguard Worker   };
191*a65addddSAndroid Build Coastguard Worker };
192*a65addddSAndroid Build Coastguard Worker 
193*a65addddSAndroid Build Coastguard Worker struct TypeInjectionRequiresNonConstBinding {
194*a65addddSAndroid Build Coastguard Worker   template <typename T>
195*a65addddSAndroid Build Coastguard Worker   struct apply;
196*a65addddSAndroid Build Coastguard Worker 
197*a65addddSAndroid Build Coastguard Worker   template <typename T>
198*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T>> {
199*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
200*a65addddSAndroid Build Coastguard Worker   };
201*a65addddSAndroid Build Coastguard Worker 
202*a65addddSAndroid Build Coastguard Worker   template <typename T>
203*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T>> {
204*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
205*a65addddSAndroid Build Coastguard Worker   };
206*a65addddSAndroid Build Coastguard Worker 
207*a65addddSAndroid Build Coastguard Worker   template <typename T>
208*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T*>> {
209*a65addddSAndroid Build Coastguard Worker     using type = Bool<true>;
210*a65addddSAndroid Build Coastguard Worker   };
211*a65addddSAndroid Build Coastguard Worker 
212*a65addddSAndroid Build Coastguard Worker   template <typename T>
213*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T&>> {
214*a65addddSAndroid Build Coastguard Worker     using type = Bool<true>;
215*a65addddSAndroid Build Coastguard Worker   };
216*a65addddSAndroid Build Coastguard Worker 
217*a65addddSAndroid Build Coastguard Worker   template <typename T>
218*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T*>> {
219*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
220*a65addddSAndroid Build Coastguard Worker   };
221*a65addddSAndroid Build Coastguard Worker 
222*a65addddSAndroid Build Coastguard Worker   template <typename T>
223*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T&>> {
224*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
225*a65addddSAndroid Build Coastguard Worker   };
226*a65addddSAndroid Build Coastguard Worker 
227*a65addddSAndroid Build Coastguard Worker   template <typename T>
228*a65addddSAndroid Build Coastguard Worker   struct apply<Type<std::shared_ptr<T>>> {
229*a65addddSAndroid Build Coastguard Worker     using type = Bool<true>;
230*a65addddSAndroid Build Coastguard Worker   };
231*a65addddSAndroid Build Coastguard Worker 
232*a65addddSAndroid Build Coastguard Worker   template <typename T>
233*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Assisted<T>>> {
234*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
235*a65addddSAndroid Build Coastguard Worker   };
236*a65addddSAndroid Build Coastguard Worker 
237*a65addddSAndroid Build Coastguard Worker   template <typename T>
238*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Provider<T>>> {
239*a65addddSAndroid Build Coastguard Worker     using type = Bool<true>;
240*a65addddSAndroid Build Coastguard Worker   };
241*a65addddSAndroid Build Coastguard Worker 
242*a65addddSAndroid Build Coastguard Worker   template <typename T>
243*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Provider<const T>>> {
244*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
245*a65addddSAndroid Build Coastguard Worker   };
246*a65addddSAndroid Build Coastguard Worker 
247*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T>
248*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, T>>> {
249*a65addddSAndroid Build Coastguard Worker     using type = TypeInjectionRequiresNonConstBinding(Type<T>);
250*a65addddSAndroid Build Coastguard Worker   };
251*a65addddSAndroid Build Coastguard Worker };
252*a65addddSAndroid Build Coastguard Worker 
253*a65addddSAndroid Build Coastguard Worker // Returns U wrapped in the same annotations in AnnotatedT (if any).
254*a65addddSAndroid Build Coastguard Worker struct CopyAnnotation {
255*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedT, typename U>
256*a65addddSAndroid Build Coastguard Worker   struct apply;
257*a65addddSAndroid Build Coastguard Worker 
258*a65addddSAndroid Build Coastguard Worker   template <typename T, typename U>
259*a65addddSAndroid Build Coastguard Worker   struct apply {
260*a65addddSAndroid Build Coastguard Worker     using type = U;
261*a65addddSAndroid Build Coastguard Worker   };
262*a65addddSAndroid Build Coastguard Worker 
263*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T, typename U>
264*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, T>>, Type<U>> {
265*a65addddSAndroid Build Coastguard Worker     using type = Type<fruit::Annotated<Annotation, U>>;
266*a65addddSAndroid Build Coastguard Worker   };
267*a65addddSAndroid Build Coastguard Worker };
268*a65addddSAndroid Build Coastguard Worker 
269*a65addddSAndroid Build Coastguard Worker struct IsValidSignature {
270*a65addddSAndroid Build Coastguard Worker   template <typename Signature>
271*a65addddSAndroid Build Coastguard Worker   struct apply {
272*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
273*a65addddSAndroid Build Coastguard Worker   };
274*a65addddSAndroid Build Coastguard Worker 
275*a65addddSAndroid Build Coastguard Worker   template <typename T, typename... Args>
276*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T(Args...)>> {
277*a65addddSAndroid Build Coastguard Worker     using type = Bool<true>;
278*a65addddSAndroid Build Coastguard Worker   };
279*a65addddSAndroid Build Coastguard Worker };
280*a65addddSAndroid Build Coastguard Worker 
281*a65addddSAndroid Build Coastguard Worker // Removes the Annotation (if any) wrapping a type T.
282*a65addddSAndroid Build Coastguard Worker struct RemoveAnnotations {
283*a65addddSAndroid Build Coastguard Worker   template <typename T>
284*a65addddSAndroid Build Coastguard Worker   struct apply;
285*a65addddSAndroid Build Coastguard Worker 
286*a65addddSAndroid Build Coastguard Worker   template <typename T>
287*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T>> {
288*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
289*a65addddSAndroid Build Coastguard Worker   };
290*a65addddSAndroid Build Coastguard Worker 
291*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T>
292*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, T>>> {
293*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
294*a65addddSAndroid Build Coastguard Worker   };
295*a65addddSAndroid Build Coastguard Worker };
296*a65addddSAndroid Build Coastguard Worker 
297*a65addddSAndroid Build Coastguard Worker // Removes the Annotation(s) (if any) wrapping the types in AnnotatedSignature.
298*a65addddSAndroid Build Coastguard Worker struct RemoveAnnotationsFromSignature {
299*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedSignature>
300*a65addddSAndroid Build Coastguard Worker   struct apply {
301*a65addddSAndroid Build Coastguard Worker     using type = ConstructError(NotASignatureErrorTag, AnnotatedSignature);
302*a65addddSAndroid Build Coastguard Worker   };
303*a65addddSAndroid Build Coastguard Worker 
304*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedT, typename... AnnotatedArgs>
305*a65addddSAndroid Build Coastguard Worker   struct apply<Type<AnnotatedT(AnnotatedArgs...)>> {
306*a65addddSAndroid Build Coastguard Worker     using type = ConsSignature(RemoveAnnotations(Type<AnnotatedT>), Id<RemoveAnnotations(Type<AnnotatedArgs>)>...);
307*a65addddSAndroid Build Coastguard Worker   };
308*a65addddSAndroid Build Coastguard Worker };
309*a65addddSAndroid Build Coastguard Worker 
310*a65addddSAndroid Build Coastguard Worker // Removes the Annotation(s) (if any) wrapping the types in the Vector V.
311*a65addddSAndroid Build Coastguard Worker struct RemoveAnnotationsFromVector {
312*a65addddSAndroid Build Coastguard Worker   template <typename V>
313*a65addddSAndroid Build Coastguard Worker   struct apply {
314*a65addddSAndroid Build Coastguard Worker     using type = TransformVector(V, RemoveAnnotations);
315*a65addddSAndroid Build Coastguard Worker   };
316*a65addddSAndroid Build Coastguard Worker };
317*a65addddSAndroid Build Coastguard Worker 
318*a65addddSAndroid Build Coastguard Worker // Maps T->T* in a possibly-annotated type.
319*a65addddSAndroid Build Coastguard Worker struct AddPointerInAnnotatedType {
320*a65addddSAndroid Build Coastguard Worker   template <typename T>
321*a65addddSAndroid Build Coastguard Worker   struct apply;
322*a65addddSAndroid Build Coastguard Worker 
323*a65addddSAndroid Build Coastguard Worker   template <typename T>
324*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T>> {
325*a65addddSAndroid Build Coastguard Worker     using type = Type<T*>;
326*a65addddSAndroid Build Coastguard Worker   };
327*a65addddSAndroid Build Coastguard Worker 
328*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T>
329*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, T>>> {
330*a65addddSAndroid Build Coastguard Worker     using type = Type<fruit::Annotated<Annotation, T*>>;
331*a65addddSAndroid Build Coastguard Worker   };
332*a65addddSAndroid Build Coastguard Worker };
333*a65addddSAndroid Build Coastguard Worker 
334*a65addddSAndroid Build Coastguard Worker // TODO: This also does UnlabelAssisted<>. Consider renaming and/or removing that logic (and
335*a65addddSAndroid Build Coastguard Worker // letting callers do the unlabeling when desired).
336*a65addddSAndroid Build Coastguard Worker struct RemoveNonAssisted {
337*a65addddSAndroid Build Coastguard Worker   template <typename V>
338*a65addddSAndroid Build Coastguard Worker   struct apply {
339*a65addddSAndroid Build Coastguard Worker     struct Helper {
340*a65addddSAndroid Build Coastguard Worker       // Non-assisted case
341*a65addddSAndroid Build Coastguard Worker       template <typename CurrentResult, typename T>
342*a65addddSAndroid Build Coastguard Worker       struct apply {
343*a65addddSAndroid Build Coastguard Worker         using type = CurrentResult;
344*a65addddSAndroid Build Coastguard Worker       };
345*a65addddSAndroid Build Coastguard Worker 
346*a65addddSAndroid Build Coastguard Worker       template <typename CurrentResult, typename T>
347*a65addddSAndroid Build Coastguard Worker       struct apply<CurrentResult, Type<Assisted<T>>> {
348*a65addddSAndroid Build Coastguard Worker         using type = PushBack(CurrentResult, Type<T>);
349*a65addddSAndroid Build Coastguard Worker       };
350*a65addddSAndroid Build Coastguard Worker     };
351*a65addddSAndroid Build Coastguard Worker 
352*a65addddSAndroid Build Coastguard Worker     using type = FoldVector(V, Helper, Vector<>);
353*a65addddSAndroid Build Coastguard Worker   };
354*a65addddSAndroid Build Coastguard Worker };
355*a65addddSAndroid Build Coastguard Worker 
356*a65addddSAndroid Build Coastguard Worker struct RemoveAssisted {
357*a65addddSAndroid Build Coastguard Worker   template <typename V>
358*a65addddSAndroid Build Coastguard Worker   struct apply {
359*a65addddSAndroid Build Coastguard Worker     struct Helper {
360*a65addddSAndroid Build Coastguard Worker       // Non-assisted case
361*a65addddSAndroid Build Coastguard Worker       template <typename CurrentResult, typename T>
362*a65addddSAndroid Build Coastguard Worker       struct apply {
363*a65addddSAndroid Build Coastguard Worker         using type = PushBack(CurrentResult, T);
364*a65addddSAndroid Build Coastguard Worker       };
365*a65addddSAndroid Build Coastguard Worker 
366*a65addddSAndroid Build Coastguard Worker       // Assisted case
367*a65addddSAndroid Build Coastguard Worker       template <typename CurrentResult, typename T>
368*a65addddSAndroid Build Coastguard Worker       struct apply<CurrentResult, Type<Assisted<T>>> {
369*a65addddSAndroid Build Coastguard Worker         using type = CurrentResult;
370*a65addddSAndroid Build Coastguard Worker       };
371*a65addddSAndroid Build Coastguard Worker     };
372*a65addddSAndroid Build Coastguard Worker 
373*a65addddSAndroid Build Coastguard Worker     using type = FoldVector(V, Helper, Vector<>);
374*a65addddSAndroid Build Coastguard Worker   };
375*a65addddSAndroid Build Coastguard Worker };
376*a65addddSAndroid Build Coastguard Worker 
377*a65addddSAndroid Build Coastguard Worker struct UnlabelAssistedSingleType {
378*a65addddSAndroid Build Coastguard Worker   template <typename T>
379*a65addddSAndroid Build Coastguard Worker   struct apply;
380*a65addddSAndroid Build Coastguard Worker 
381*a65addddSAndroid Build Coastguard Worker   template <typename T>
382*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T>> {
383*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
384*a65addddSAndroid Build Coastguard Worker   };
385*a65addddSAndroid Build Coastguard Worker 
386*a65addddSAndroid Build Coastguard Worker   template <typename T>
387*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Assisted<T>>> {
388*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
389*a65addddSAndroid Build Coastguard Worker   };
390*a65addddSAndroid Build Coastguard Worker };
391*a65addddSAndroid Build Coastguard Worker 
392*a65addddSAndroid Build Coastguard Worker struct UnlabelAssisted {
393*a65addddSAndroid Build Coastguard Worker   template <typename V>
394*a65addddSAndroid Build Coastguard Worker   struct apply {
395*a65addddSAndroid Build Coastguard Worker     using type = TransformVector(V, UnlabelAssistedSingleType);
396*a65addddSAndroid Build Coastguard Worker   };
397*a65addddSAndroid Build Coastguard Worker };
398*a65addddSAndroid Build Coastguard Worker 
399*a65addddSAndroid Build Coastguard Worker struct RequiredLambdaArgsForAssistedFactory {
400*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedSignature>
401*a65addddSAndroid Build Coastguard Worker   struct apply {
402*a65addddSAndroid Build Coastguard Worker     using type = RemoveAnnotationsFromVector(UnlabelAssisted(SignatureArgs(AnnotatedSignature)));
403*a65addddSAndroid Build Coastguard Worker   };
404*a65addddSAndroid Build Coastguard Worker };
405*a65addddSAndroid Build Coastguard Worker 
406*a65addddSAndroid Build Coastguard Worker struct RequiredLambdaSignatureForAssistedFactory {
407*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedSignature>
408*a65addddSAndroid Build Coastguard Worker   struct apply {
409*a65addddSAndroid Build Coastguard Worker     using type = ConsSignatureWithVector(RemoveAnnotations(SignatureType(AnnotatedSignature)),
410*a65addddSAndroid Build Coastguard Worker                                          RequiredLambdaArgsForAssistedFactory(AnnotatedSignature));
411*a65addddSAndroid Build Coastguard Worker   };
412*a65addddSAndroid Build Coastguard Worker };
413*a65addddSAndroid Build Coastguard Worker 
414*a65addddSAndroid Build Coastguard Worker struct InjectedFunctionArgsForAssistedFactory {
415*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedSignature>
416*a65addddSAndroid Build Coastguard Worker   struct apply {
417*a65addddSAndroid Build Coastguard Worker     using type = RemoveNonAssisted(SignatureArgs(AnnotatedSignature));
418*a65addddSAndroid Build Coastguard Worker   };
419*a65addddSAndroid Build Coastguard Worker };
420*a65addddSAndroid Build Coastguard Worker 
421*a65addddSAndroid Build Coastguard Worker struct InjectedSignatureForAssistedFactory {
422*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedSignature>
423*a65addddSAndroid Build Coastguard Worker   struct apply {
424*a65addddSAndroid Build Coastguard Worker     using type = ConsSignatureWithVector(RemoveAnnotations(SignatureType(AnnotatedSignature)),
425*a65addddSAndroid Build Coastguard Worker                                          InjectedFunctionArgsForAssistedFactory(AnnotatedSignature));
426*a65addddSAndroid Build Coastguard Worker   };
427*a65addddSAndroid Build Coastguard Worker };
428*a65addddSAndroid Build Coastguard Worker 
429*a65addddSAndroid Build Coastguard Worker struct IsAssisted {
430*a65addddSAndroid Build Coastguard Worker   template <typename T>
431*a65addddSAndroid Build Coastguard Worker   struct apply {
432*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
433*a65addddSAndroid Build Coastguard Worker   };
434*a65addddSAndroid Build Coastguard Worker 
435*a65addddSAndroid Build Coastguard Worker   template <typename T>
436*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Assisted<T>>> {
437*a65addddSAndroid Build Coastguard Worker     using type = Bool<true>;
438*a65addddSAndroid Build Coastguard Worker   };
439*a65addddSAndroid Build Coastguard Worker };
440*a65addddSAndroid Build Coastguard Worker 
441*a65addddSAndroid Build Coastguard Worker struct NumAssisted {
442*a65addddSAndroid Build Coastguard Worker   template <typename V>
443*a65addddSAndroid Build Coastguard Worker   struct apply;
444*a65addddSAndroid Build Coastguard Worker 
445*a65addddSAndroid Build Coastguard Worker   template <typename... Types>
446*a65addddSAndroid Build Coastguard Worker   struct apply<Vector<Types...>> {
447*a65addddSAndroid Build Coastguard Worker     using type = SumAll(typename IsAssisted::apply<Types>::type...);
448*a65addddSAndroid Build Coastguard Worker   };
449*a65addddSAndroid Build Coastguard Worker };
450*a65addddSAndroid Build Coastguard Worker 
451*a65addddSAndroid Build Coastguard Worker // Counts the number of Assisted<> types in V before the given index.
452*a65addddSAndroid Build Coastguard Worker struct NumAssistedBefore {
453*a65addddSAndroid Build Coastguard Worker   template <typename Index, typename V>
454*a65addddSAndroid Build Coastguard Worker   struct apply;
455*a65addddSAndroid Build Coastguard Worker 
456*a65addddSAndroid Build Coastguard Worker   template <typename V>
457*a65addddSAndroid Build Coastguard Worker   struct apply<Int<0>, V> {
458*a65addddSAndroid Build Coastguard Worker     using type = Int<0>;
459*a65addddSAndroid Build Coastguard Worker   };
460*a65addddSAndroid Build Coastguard Worker 
461*a65addddSAndroid Build Coastguard Worker   template <int n, typename V>
462*a65addddSAndroid Build Coastguard Worker   struct apply<Int<n>, V> {
463*a65addddSAndroid Build Coastguard Worker     using N = Int<n>;
464*a65addddSAndroid Build Coastguard Worker     using type = Minus(NumAssisted(V), NumAssisted(VectorRemoveFirstN(V, N)));
465*a65addddSAndroid Build Coastguard Worker   };
466*a65addddSAndroid Build Coastguard Worker };
467*a65addddSAndroid Build Coastguard Worker 
468*a65addddSAndroid Build Coastguard Worker // Checks whether C is auto-injectable thanks to an Inject typedef.
469*a65addddSAndroid Build Coastguard Worker struct HasInjectAnnotation {
470*a65addddSAndroid Build Coastguard Worker   template <typename C>
471*a65addddSAndroid Build Coastguard Worker   struct apply;
472*a65addddSAndroid Build Coastguard Worker 
473*a65addddSAndroid Build Coastguard Worker   template <typename C>
474*a65addddSAndroid Build Coastguard Worker   struct apply<Type<C>> {
475*a65addddSAndroid Build Coastguard Worker     template <typename C1>
476*a65addddSAndroid Build Coastguard Worker     static Bool<true> test(typename C1::Inject*);
477*a65addddSAndroid Build Coastguard Worker 
478*a65addddSAndroid Build Coastguard Worker     template <typename>
479*a65addddSAndroid Build Coastguard Worker     static Bool<false> test(...);
480*a65addddSAndroid Build Coastguard Worker 
481*a65addddSAndroid Build Coastguard Worker     using type = decltype(test<C>(nullptr));
482*a65addddSAndroid Build Coastguard Worker   };
483*a65addddSAndroid Build Coastguard Worker };
484*a65addddSAndroid Build Coastguard Worker 
485*a65addddSAndroid Build Coastguard Worker struct DoGetInjectAnnotation {
486*a65addddSAndroid Build Coastguard Worker   template <typename C>
487*a65addddSAndroid Build Coastguard Worker   struct apply;
488*a65addddSAndroid Build Coastguard Worker 
489*a65addddSAndroid Build Coastguard Worker   template <typename C>
490*a65addddSAndroid Build Coastguard Worker   struct apply<Type<C>> {
491*a65addddSAndroid Build Coastguard Worker     using type = Type<typename C::Inject>;
492*a65addddSAndroid Build Coastguard Worker   };
493*a65addddSAndroid Build Coastguard Worker };
494*a65addddSAndroid Build Coastguard Worker 
495*a65addddSAndroid Build Coastguard Worker struct GetInjectAnnotation {
496*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedC>
497*a65addddSAndroid Build Coastguard Worker   struct apply {
498*a65addddSAndroid Build Coastguard Worker     using C = RemoveAnnotations(AnnotatedC);
499*a65addddSAndroid Build Coastguard Worker     using DecoratedS = DoGetInjectAnnotation(C);
500*a65addddSAndroid Build Coastguard Worker     using SResult = SignatureType(DecoratedS);
501*a65addddSAndroid Build Coastguard Worker     using AnnotatedSArgs = SignatureArgs(DecoratedS);
502*a65addddSAndroid Build Coastguard Worker     using SArgs = RemoveAnnotationsFromVector(UnlabelAssisted(AnnotatedSArgs));
503*a65addddSAndroid Build Coastguard Worker     // We replace the non-annotated return type with the potentially-annotated AnnotatedC.
504*a65addddSAndroid Build Coastguard Worker     using AnnotatedDecoratedS = ConsSignatureWithVector(AnnotatedC, AnnotatedSArgs);
505*a65addddSAndroid Build Coastguard Worker     using type = If(IsAbstract(C), ConstructError(CannotConstructAbstractClassErrorTag, C),
506*a65addddSAndroid Build Coastguard Worker                     If(Not(IsValidSignature(DecoratedS)),
507*a65addddSAndroid Build Coastguard Worker                        ConstructError(InjectTypedefNotASignatureErrorTag, C, DecoratedS),
508*a65addddSAndroid Build Coastguard Worker                        If(Not(IsSame(SResult, RemoveAnnotations(SResult))),
509*a65addddSAndroid Build Coastguard Worker                           ConstructError(InjectTypedefWithAnnotationErrorTag, C),
510*a65addddSAndroid Build Coastguard Worker                           If(Not(IsSame(C, SResult)), ConstructError(InjectTypedefForWrongClassErrorTag, C, SResult),
511*a65addddSAndroid Build Coastguard Worker                              If(Not(IsConstructibleWithVector(C, SArgs)),
512*a65addddSAndroid Build Coastguard Worker                                 ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C,
513*a65addddSAndroid Build Coastguard Worker                                                ConsSignatureWithVector(SResult, SArgs)),
514*a65addddSAndroid Build Coastguard Worker                                 AnnotatedDecoratedS)))));
515*a65addddSAndroid Build Coastguard Worker   };
516*a65addddSAndroid Build Coastguard Worker };
517*a65addddSAndroid Build Coastguard Worker 
518*a65addddSAndroid Build Coastguard Worker //********************************************************************************************************************************
519*a65addddSAndroid Build Coastguard Worker // Part 2: Type functors involving at least one ConsComp.
520*a65addddSAndroid Build Coastguard Worker //********************************************************************************************************************************
521*a65addddSAndroid Build Coastguard Worker 
522*a65addddSAndroid Build Coastguard Worker template <typename RsSupersetParam, typename PsParam, typename NonConstRsPsParam,
523*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
524*a65addddSAndroid Build Coastguard Worker           typename DepsParam,
525*a65addddSAndroid Build Coastguard Worker #endif
526*a65addddSAndroid Build Coastguard Worker           typename InterfaceBindingsParam, typename DeferredBindingFunctorsParam>
527*a65addddSAndroid Build Coastguard Worker struct Comp {
528*a65addddSAndroid Build Coastguard Worker   // The actual set of requirements is SetDifference(RsSuperset, Ps)
529*a65addddSAndroid Build Coastguard Worker   // We don't store Rs explicitly because we'd need to remove elements very often (and that's slow).
530*a65addddSAndroid Build Coastguard Worker   using RsSuperset = RsSupersetParam;
531*a65addddSAndroid Build Coastguard Worker 
532*a65addddSAndroid Build Coastguard Worker   using Ps = PsParam;
533*a65addddSAndroid Build Coastguard Worker   // This is a set of normalized types.
534*a65addddSAndroid Build Coastguard Worker   // - If a type is in SetDifference(RsSuperset, Ps) and not here: it's required as const only
535*a65addddSAndroid Build Coastguard Worker   // - If a type is in SetDifference(RsSuperset, Ps) and also here: it's required as non-const
536*a65addddSAndroid Build Coastguard Worker   // - If a type is in Ps and not here: it's provided as const only
537*a65addddSAndroid Build Coastguard Worker   // - If a type is in Ps and also here: it's provided as non-const
538*a65addddSAndroid Build Coastguard Worker   using NonConstRsPs = NonConstRsPsParam;
539*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
540*a65addddSAndroid Build Coastguard Worker   using Deps = DepsParam;
541*a65addddSAndroid Build Coastguard Worker #endif
542*a65addddSAndroid Build Coastguard Worker   using InterfaceBindings = InterfaceBindingsParam;
543*a65addddSAndroid Build Coastguard Worker   using DeferredBindingFunctors = DeferredBindingFunctorsParam;
544*a65addddSAndroid Build Coastguard Worker 
545*a65addddSAndroid Build Coastguard Worker   // Invariants:
546*a65addddSAndroid Build Coastguard Worker   // * all types appearing as arguments of Deps are in Rs
547*a65addddSAndroid Build Coastguard Worker   // * all types in Ps are at the head of one (and only one) Dep.
548*a65addddSAndroid Build Coastguard Worker   //   (note that the types in Rs can appear in deps any number of times, 0 is also ok)
549*a65addddSAndroid Build Coastguard Worker   // * Deps is of the form Vector<Dep...> with each Dep of the form T(Args...) and where Vector<Args...> is a set (no
550*a65addddSAndroid Build Coastguard Worker   // repetitions).
551*a65addddSAndroid Build Coastguard Worker   // * Bindings is a proof tree forest, with injected classes as formulas.
552*a65addddSAndroid Build Coastguard Worker   // * Each element X of the list DeferredBindingFunctors has:
553*a65addddSAndroid Build Coastguard Worker   //   - a default-constructible X::apply<Comp> type
554*a65addddSAndroid Build Coastguard Worker   //   - a void X::apply<Comp>::operator(ComponentStorage&)
555*a65addddSAndroid Build Coastguard Worker   //   - an X::apply<Comp>::Result type
556*a65addddSAndroid Build Coastguard Worker   // * Each element of NonConstRsPs is in RsSuperset or in Ps (or both)
557*a65addddSAndroid Build Coastguard Worker };
558*a65addddSAndroid Build Coastguard Worker 
559*a65addddSAndroid Build Coastguard Worker // Using ConsComp instead of Comp<...> in a meta-expression allows the types to be evaluated.
560*a65addddSAndroid Build Coastguard Worker // See ConsVector for more details.
561*a65addddSAndroid Build Coastguard Worker struct ConsComp {
562*a65addddSAndroid Build Coastguard Worker   template <typename RsSupersetParam, typename PsParam, typename NonConstRsPsParam,
563*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
564*a65addddSAndroid Build Coastguard Worker             typename DepsParam,
565*a65addddSAndroid Build Coastguard Worker #endif
566*a65addddSAndroid Build Coastguard Worker             typename InterfaceBindingsParam, typename DeferredBindingFunctorsParam>
567*a65addddSAndroid Build Coastguard Worker   struct apply {
568*a65addddSAndroid Build Coastguard Worker     using type = Comp<RsSupersetParam, PsParam, NonConstRsPsParam,
569*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
570*a65addddSAndroid Build Coastguard Worker                       DepsParam,
571*a65addddSAndroid Build Coastguard Worker #endif
572*a65addddSAndroid Build Coastguard Worker                       InterfaceBindingsParam, DeferredBindingFunctorsParam>;
573*a65addddSAndroid Build Coastguard Worker   };
574*a65addddSAndroid Build Coastguard Worker };
575*a65addddSAndroid Build Coastguard Worker 
576*a65addddSAndroid Build Coastguard Worker struct GetComponentDeps {
577*a65addddSAndroid Build Coastguard Worker   template <typename Comp>
578*a65addddSAndroid Build Coastguard Worker   struct apply {
579*a65addddSAndroid Build Coastguard Worker     using type = typename Comp::Deps;
580*a65addddSAndroid Build Coastguard Worker   };
581*a65addddSAndroid Build Coastguard Worker };
582*a65addddSAndroid Build Coastguard Worker 
583*a65addddSAndroid Build Coastguard Worker struct GetComponentPs {
584*a65addddSAndroid Build Coastguard Worker   template <typename Comp>
585*a65addddSAndroid Build Coastguard Worker   struct apply {
586*a65addddSAndroid Build Coastguard Worker     using type = typename Comp::Ps;
587*a65addddSAndroid Build Coastguard Worker   };
588*a65addddSAndroid Build Coastguard Worker };
589*a65addddSAndroid Build Coastguard Worker 
590*a65addddSAndroid Build Coastguard Worker struct GetComponentRsSuperset {
591*a65addddSAndroid Build Coastguard Worker   template <typename Comp>
592*a65addddSAndroid Build Coastguard Worker   struct apply {
593*a65addddSAndroid Build Coastguard Worker     using type = typename Comp::RsSuperset;
594*a65addddSAndroid Build Coastguard Worker   };
595*a65addddSAndroid Build Coastguard Worker };
596*a65addddSAndroid Build Coastguard Worker 
597*a65addddSAndroid Build Coastguard Worker struct GetComponentNonConstRsPs {
598*a65addddSAndroid Build Coastguard Worker   template <typename Comp>
599*a65addddSAndroid Build Coastguard Worker   struct apply {
600*a65addddSAndroid Build Coastguard Worker     using type = typename Comp::NonConstRsPs;
601*a65addddSAndroid Build Coastguard Worker   };
602*a65addddSAndroid Build Coastguard Worker };
603*a65addddSAndroid Build Coastguard Worker 
604*a65addddSAndroid Build Coastguard Worker struct IsInjectableBareType {
605*a65addddSAndroid Build Coastguard Worker   template <typename T>
606*a65addddSAndroid Build Coastguard Worker   struct apply;
607*a65addddSAndroid Build Coastguard Worker 
608*a65addddSAndroid Build Coastguard Worker   template <typename T>
609*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T>> {
610*a65addddSAndroid Build Coastguard Worker     using type = Bool<std::is_arithmetic<T>::value || std::is_class<T>::value || std::is_enum<T>::value>;
611*a65addddSAndroid Build Coastguard Worker   };
612*a65addddSAndroid Build Coastguard Worker 
613*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T>
614*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, T>>> {
615*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
616*a65addddSAndroid Build Coastguard Worker   };
617*a65addddSAndroid Build Coastguard Worker 
618*a65addddSAndroid Build Coastguard Worker   template <typename T>
619*a65addddSAndroid Build Coastguard Worker   struct apply<Type<std::shared_ptr<T>>> {
620*a65addddSAndroid Build Coastguard Worker     using type = Bool<false>;
621*a65addddSAndroid Build Coastguard Worker   };
622*a65addddSAndroid Build Coastguard Worker };
623*a65addddSAndroid Build Coastguard Worker 
624*a65addddSAndroid Build Coastguard Worker // Checks if T is a (non-annotated) injectable type.
625*a65addddSAndroid Build Coastguard Worker struct IsInjectableType {
626*a65addddSAndroid Build Coastguard Worker   template <typename T>
627*a65addddSAndroid Build Coastguard Worker   struct apply {
628*a65addddSAndroid Build Coastguard Worker     using type = IsInjectableBareType(NormalizeType(T));
629*a65addddSAndroid Build Coastguard Worker   };
630*a65addddSAndroid Build Coastguard Worker };
631*a65addddSAndroid Build Coastguard Worker 
632*a65addddSAndroid Build Coastguard Worker // Checks that T is a (non-annotated) injectable type. If it isn't this returns an error, otherwise it returns None.
633*a65addddSAndroid Build Coastguard Worker struct CheckInjectableType {
634*a65addddSAndroid Build Coastguard Worker   template <typename T>
635*a65addddSAndroid Build Coastguard Worker   struct apply {
636*a65addddSAndroid Build Coastguard Worker     using type = If(Not(IsInjectableType(T)), ConstructError(NonInjectableTypeErrorTag, T), None);
637*a65addddSAndroid Build Coastguard Worker   };
638*a65addddSAndroid Build Coastguard Worker };
639*a65addddSAndroid Build Coastguard Worker 
640*a65addddSAndroid Build Coastguard Worker // Checks that Types... are (non-annotated) injectable types. If they have an annotation or they are not injectable it
641*a65addddSAndroid Build Coastguard Worker // an appropriate error is returned.
642*a65addddSAndroid Build Coastguard Worker // Otherwise this returns None.
643*a65addddSAndroid Build Coastguard Worker struct CheckInjectableTypeVector {
644*a65addddSAndroid Build Coastguard Worker   struct Helper {
645*a65addddSAndroid Build Coastguard Worker     template <typename CurrentResult, typename T>
646*a65addddSAndroid Build Coastguard Worker     struct apply {
647*a65addddSAndroid Build Coastguard Worker       using type = PropagateError(CheckInjectableType(T), CurrentResult);
648*a65addddSAndroid Build Coastguard Worker     };
649*a65addddSAndroid Build Coastguard Worker   };
650*a65addddSAndroid Build Coastguard Worker 
651*a65addddSAndroid Build Coastguard Worker   template <typename V>
652*a65addddSAndroid Build Coastguard Worker   struct apply {
653*a65addddSAndroid Build Coastguard Worker     using type = FoldVector(V, Helper, None);
654*a65addddSAndroid Build Coastguard Worker   };
655*a65addddSAndroid Build Coastguard Worker };
656*a65addddSAndroid Build Coastguard Worker 
657*a65addddSAndroid Build Coastguard Worker // Checks that Types... are normalized and injectable types. If not it returns an appropriate error.
658*a65addddSAndroid Build Coastguard Worker // If they are all normalized types this returns Result.
659*a65addddSAndroid Build Coastguard Worker struct CheckNormalizedTypes {
660*a65addddSAndroid Build Coastguard Worker   template <typename V>
661*a65addddSAndroid Build Coastguard Worker   struct apply;
662*a65addddSAndroid Build Coastguard Worker 
663*a65addddSAndroid Build Coastguard Worker   template <typename... Types>
664*a65addddSAndroid Build Coastguard Worker   struct apply<Vector<Type<Types>...>> {
665*a65addddSAndroid Build Coastguard Worker     struct Helper {
666*a65addddSAndroid Build Coastguard Worker       template <typename CurrentResult, typename T>
667*a65addddSAndroid Build Coastguard Worker       struct apply {
668*a65addddSAndroid Build Coastguard Worker         using NormalizedType = NormalizeType(T);
669*a65addddSAndroid Build Coastguard Worker         using type = PropagateError(CheckInjectableType(RemoveAnnotations(NormalizeUntilStable(T))),
670*a65addddSAndroid Build Coastguard Worker                                     If(Not(IsSame(NormalizeType(T), T)),
671*a65addddSAndroid Build Coastguard Worker                                        ConstructError(NonClassTypeErrorTag, RemoveAnnotations(T),
672*a65addddSAndroid Build Coastguard Worker                                                       RemoveAnnotations(NormalizeUntilStable(T))),
673*a65addddSAndroid Build Coastguard Worker                                        CurrentResult));
674*a65addddSAndroid Build Coastguard Worker       };
675*a65addddSAndroid Build Coastguard Worker     };
676*a65addddSAndroid Build Coastguard Worker 
677*a65addddSAndroid Build Coastguard Worker     using type = Fold(Helper, None, Type<Types>...);
678*a65addddSAndroid Build Coastguard Worker   };
679*a65addddSAndroid Build Coastguard Worker };
680*a65addddSAndroid Build Coastguard Worker 
681*a65addddSAndroid Build Coastguard Worker // Checks that Types... are not annotated types. If they have an annotation it returns an appropriate error.
682*a65addddSAndroid Build Coastguard Worker // If none of them is annotated, this returns None.
683*a65addddSAndroid Build Coastguard Worker struct CheckNotAnnotatedTypes {
684*a65addddSAndroid Build Coastguard Worker   template <typename V>
685*a65addddSAndroid Build Coastguard Worker   struct apply;
686*a65addddSAndroid Build Coastguard Worker 
687*a65addddSAndroid Build Coastguard Worker   template <typename... Types>
688*a65addddSAndroid Build Coastguard Worker   struct apply<Vector<Type<Types>...>> {
689*a65addddSAndroid Build Coastguard Worker     struct Helper {
690*a65addddSAndroid Build Coastguard Worker       template <typename CurrentResult, typename T>
691*a65addddSAndroid Build Coastguard Worker       struct apply {
692*a65addddSAndroid Build Coastguard Worker         using TypeWithoutAnnotations = RemoveAnnotations(T);
693*a65addddSAndroid Build Coastguard Worker         using type = If(Not(IsSame(TypeWithoutAnnotations, T)),
694*a65addddSAndroid Build Coastguard Worker                         ConstructError(AnnotatedTypeErrorTag, T, TypeWithoutAnnotations), CurrentResult);
695*a65addddSAndroid Build Coastguard Worker       };
696*a65addddSAndroid Build Coastguard Worker     };
697*a65addddSAndroid Build Coastguard Worker 
698*a65addddSAndroid Build Coastguard Worker     using type = Fold(Helper, None, Type<Types>...);
699*a65addddSAndroid Build Coastguard Worker   };
700*a65addddSAndroid Build Coastguard Worker };
701*a65addddSAndroid Build Coastguard Worker 
702*a65addddSAndroid Build Coastguard Worker // Check that there are no fruit::Required<> types in Component/NormalizedComponent's arguments.
703*a65addddSAndroid Build Coastguard Worker // If there aren't any, this returns None.
704*a65addddSAndroid Build Coastguard Worker struct CheckNoRequiredTypesInComponentArguments {
705*a65addddSAndroid Build Coastguard Worker   template <typename V>
706*a65addddSAndroid Build Coastguard Worker   struct apply;
707*a65addddSAndroid Build Coastguard Worker 
708*a65addddSAndroid Build Coastguard Worker   template <typename... Types>
709*a65addddSAndroid Build Coastguard Worker   struct apply<Vector<Types...>> {
710*a65addddSAndroid Build Coastguard Worker     using type = None;
711*a65addddSAndroid Build Coastguard Worker   };
712*a65addddSAndroid Build Coastguard Worker 
713*a65addddSAndroid Build Coastguard Worker   template <typename T, typename... OtherTypes>
714*a65addddSAndroid Build Coastguard Worker   struct apply<Vector<Type<T>, OtherTypes...>> {
715*a65addddSAndroid Build Coastguard Worker     using type = CheckNoRequiredTypesInComponentArguments(Vector<OtherTypes...>);
716*a65addddSAndroid Build Coastguard Worker   };
717*a65addddSAndroid Build Coastguard Worker 
718*a65addddSAndroid Build Coastguard Worker   template <typename... RequiredArgs, typename... OtherTypes>
719*a65addddSAndroid Build Coastguard Worker   struct apply<Vector<Type<fruit::Required<RequiredArgs...>>, OtherTypes...>> {
720*a65addddSAndroid Build Coastguard Worker     using type = ConstructError(RequiredTypesInComponentArgumentsErrorTag, Type<fruit::Required<RequiredArgs...>>);
721*a65addddSAndroid Build Coastguard Worker   };
722*a65addddSAndroid Build Coastguard Worker };
723*a65addddSAndroid Build Coastguard Worker 
724*a65addddSAndroid Build Coastguard Worker // Check that there are no fruit::Required<> types in Injector's arguments.
725*a65addddSAndroid Build Coastguard Worker // If there aren't any, this returns None.
726*a65addddSAndroid Build Coastguard Worker struct CheckNoRequiredTypesInInjectorArguments {
727*a65addddSAndroid Build Coastguard Worker   template <typename... Types>
728*a65addddSAndroid Build Coastguard Worker   struct apply {
729*a65addddSAndroid Build Coastguard Worker     using type = None;
730*a65addddSAndroid Build Coastguard Worker   };
731*a65addddSAndroid Build Coastguard Worker 
732*a65addddSAndroid Build Coastguard Worker   template <typename T, typename... Types>
733*a65addddSAndroid Build Coastguard Worker   struct apply<T, Types...> {
734*a65addddSAndroid Build Coastguard Worker     using type = CheckNoRequiredTypesInInjectorArguments(Types...);
735*a65addddSAndroid Build Coastguard Worker   };
736*a65addddSAndroid Build Coastguard Worker 
737*a65addddSAndroid Build Coastguard Worker   template <typename... RequiredArgs, typename... Types>
738*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Required<RequiredArgs...>>, Types...> {
739*a65addddSAndroid Build Coastguard Worker     using type = ConstructError(InjectorWithRequirementsErrorTag, Type<RequiredArgs>...);
740*a65addddSAndroid Build Coastguard Worker   };
741*a65addddSAndroid Build Coastguard Worker };
742*a65addddSAndroid Build Coastguard Worker 
743*a65addddSAndroid Build Coastguard Worker // Checks that there are no repetitions in Types. If there are, it returns an appropriate error.
744*a65addddSAndroid Build Coastguard Worker // If there are no repetitions it returns None.
745*a65addddSAndroid Build Coastguard Worker struct CheckNoRepeatedTypes {
746*a65addddSAndroid Build Coastguard Worker   template <typename V>
747*a65addddSAndroid Build Coastguard Worker   struct apply;
748*a65addddSAndroid Build Coastguard Worker 
749*a65addddSAndroid Build Coastguard Worker   template <typename... Types>
750*a65addddSAndroid Build Coastguard Worker   struct apply<Vector<Types...>> {
751*a65addddSAndroid Build Coastguard Worker     using type = If(HasDuplicates(Vector<Types...>), ConstructError(RepeatedTypesErrorTag, Types...), None);
752*a65addddSAndroid Build Coastguard Worker   };
753*a65addddSAndroid Build Coastguard Worker };
754*a65addddSAndroid Build Coastguard Worker 
755*a65addddSAndroid Build Coastguard Worker struct RemoveConstFromType {
756*a65addddSAndroid Build Coastguard Worker   template <typename T>
757*a65addddSAndroid Build Coastguard Worker   struct apply;
758*a65addddSAndroid Build Coastguard Worker 
759*a65addddSAndroid Build Coastguard Worker   template <typename T>
760*a65addddSAndroid Build Coastguard Worker   struct apply<Type<T>> {
761*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
762*a65addddSAndroid Build Coastguard Worker   };
763*a65addddSAndroid Build Coastguard Worker 
764*a65addddSAndroid Build Coastguard Worker   template <typename T>
765*a65addddSAndroid Build Coastguard Worker   struct apply<Type<const T>> {
766*a65addddSAndroid Build Coastguard Worker     using type = Type<T>;
767*a65addddSAndroid Build Coastguard Worker   };
768*a65addddSAndroid Build Coastguard Worker 
769*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T>
770*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, T>>> {
771*a65addddSAndroid Build Coastguard Worker     using type = Type<fruit::Annotated<Annotation, T>>;
772*a65addddSAndroid Build Coastguard Worker   };
773*a65addddSAndroid Build Coastguard Worker 
774*a65addddSAndroid Build Coastguard Worker   template <typename Annotation, typename T>
775*a65addddSAndroid Build Coastguard Worker   struct apply<Type<fruit::Annotated<Annotation, const T>>> {
776*a65addddSAndroid Build Coastguard Worker     using type = Type<fruit::Annotated<Annotation, T>>;
777*a65addddSAndroid Build Coastguard Worker   };
778*a65addddSAndroid Build Coastguard Worker };
779*a65addddSAndroid Build Coastguard Worker 
780*a65addddSAndroid Build Coastguard Worker struct RemoveConstFromTypes {
781*a65addddSAndroid Build Coastguard Worker   template <typename V>
782*a65addddSAndroid Build Coastguard Worker   struct apply;
783*a65addddSAndroid Build Coastguard Worker 
784*a65addddSAndroid Build Coastguard Worker   template <typename... Types>
785*a65addddSAndroid Build Coastguard Worker   struct apply<Vector<Types...>> {
786*a65addddSAndroid Build Coastguard Worker     using type = ConsVector(Id<RemoveConstFromType(Types)>...);
787*a65addddSAndroid Build Coastguard Worker   };
788*a65addddSAndroid Build Coastguard Worker };
789*a65addddSAndroid Build Coastguard Worker 
790*a65addddSAndroid Build Coastguard Worker struct RemoveConstTypes {
791*a65addddSAndroid Build Coastguard Worker   struct Helper {
792*a65addddSAndroid Build Coastguard Worker     template <typename Acc, typename T>
793*a65addddSAndroid Build Coastguard Worker     struct apply;
794*a65addddSAndroid Build Coastguard Worker 
795*a65addddSAndroid Build Coastguard Worker     template <typename... AccContent, typename T>
796*a65addddSAndroid Build Coastguard Worker     struct apply<Vector<AccContent...>, Type<const T>> {
797*a65addddSAndroid Build Coastguard Worker       using type = Vector<AccContent...>;
798*a65addddSAndroid Build Coastguard Worker     };
799*a65addddSAndroid Build Coastguard Worker 
800*a65addddSAndroid Build Coastguard Worker     template <typename... AccContent, typename T>
801*a65addddSAndroid Build Coastguard Worker     struct apply<Vector<AccContent...>, Type<T>> {
802*a65addddSAndroid Build Coastguard Worker       using type = Vector<AccContent..., Type<T>>;
803*a65addddSAndroid Build Coastguard Worker     };
804*a65addddSAndroid Build Coastguard Worker 
805*a65addddSAndroid Build Coastguard Worker     template <typename... AccContent, typename Annotation, typename T>
806*a65addddSAndroid Build Coastguard Worker     struct apply<Vector<AccContent...>, Type<fruit::Annotated<Annotation, const T>>> {
807*a65addddSAndroid Build Coastguard Worker       using type = Vector<AccContent...>;
808*a65addddSAndroid Build Coastguard Worker     };
809*a65addddSAndroid Build Coastguard Worker 
810*a65addddSAndroid Build Coastguard Worker     template <typename... AccContent, typename Annotation, typename T>
811*a65addddSAndroid Build Coastguard Worker     struct apply<Vector<AccContent...>, Type<fruit::Annotated<Annotation, T>>> {
812*a65addddSAndroid Build Coastguard Worker       using type = Vector<AccContent..., Type<fruit::Annotated<Annotation, T>>>;
813*a65addddSAndroid Build Coastguard Worker     };
814*a65addddSAndroid Build Coastguard Worker   };
815*a65addddSAndroid Build Coastguard Worker 
816*a65addddSAndroid Build Coastguard Worker   template <typename V>
817*a65addddSAndroid Build Coastguard Worker   struct apply {
818*a65addddSAndroid Build Coastguard Worker     using type = FoldVector(V, Helper, Vector<>);
819*a65addddSAndroid Build Coastguard Worker   };
820*a65addddSAndroid Build Coastguard Worker };
821*a65addddSAndroid Build Coastguard Worker 
822*a65addddSAndroid Build Coastguard Worker // From a vector of injected types, this filters out the types that only require const bindings and then normalizes
823*a65addddSAndroid Build Coastguard Worker // the types in the result.
824*a65addddSAndroid Build Coastguard Worker struct NormalizedNonConstTypesIn {
825*a65addddSAndroid Build Coastguard Worker   struct Helper {
826*a65addddSAndroid Build Coastguard Worker     template <typename Acc, typename T>
827*a65addddSAndroid Build Coastguard Worker     struct apply {
828*a65addddSAndroid Build Coastguard Worker       using type = If(TypeInjectionRequiresNonConstBinding(T), PushBack(Acc, NormalizeType(T)), Acc);
829*a65addddSAndroid Build Coastguard Worker     };
830*a65addddSAndroid Build Coastguard Worker   };
831*a65addddSAndroid Build Coastguard Worker 
832*a65addddSAndroid Build Coastguard Worker   template <typename V>
833*a65addddSAndroid Build Coastguard Worker   struct apply {
834*a65addddSAndroid Build Coastguard Worker     using type = FoldVector(V, Helper, Vector<>);
835*a65addddSAndroid Build Coastguard Worker   };
836*a65addddSAndroid Build Coastguard Worker };
837*a65addddSAndroid Build Coastguard Worker 
838*a65addddSAndroid Build Coastguard Worker struct ConstructComponentImpl {
839*a65addddSAndroid Build Coastguard Worker   // Non-specialized case: no requirements.
840*a65addddSAndroid Build Coastguard Worker   template <typename... Ps>
841*a65addddSAndroid Build Coastguard Worker   struct apply {
842*a65addddSAndroid Build Coastguard Worker     using type = PropagateError(
843*a65addddSAndroid Build Coastguard Worker         CheckNoRepeatedTypes(RemoveConstFromTypes(Vector<Ps...>)),
844*a65addddSAndroid Build Coastguard Worker         PropagateError(CheckNormalizedTypes(RemoveConstFromTypes(Vector<Ps...>)),
845*a65addddSAndroid Build Coastguard Worker                        PropagateError(CheckNoRequiredTypesInComponentArguments(Vector<Ps...>),
846*a65addddSAndroid Build Coastguard Worker                                       ConsComp(EmptySet, VectorToSetUnchecked(RemoveConstFromTypes(Vector<Ps...>)),
847*a65addddSAndroid Build Coastguard Worker                                                RemoveConstTypes(Vector<Ps...>),
848*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
849*a65addddSAndroid Build Coastguard Worker                                                Vector<Pair<Ps, Vector<>>...>,
850*a65addddSAndroid Build Coastguard Worker #endif
851*a65addddSAndroid Build Coastguard Worker                                                Vector<>, EmptyList))));
852*a65addddSAndroid Build Coastguard Worker   };
853*a65addddSAndroid Build Coastguard Worker 
854*a65addddSAndroid Build Coastguard Worker   // With requirements.
855*a65addddSAndroid Build Coastguard Worker   template <typename... Rs, typename... Ps>
856*a65addddSAndroid Build Coastguard Worker   struct apply<Type<Required<Rs...>>, Ps...> {
857*a65addddSAndroid Build Coastguard Worker     using type1 = PropagateError(
858*a65addddSAndroid Build Coastguard Worker         CheckNoRepeatedTypes(RemoveConstFromTypes(Vector<Type<Rs>..., Ps...>)),
859*a65addddSAndroid Build Coastguard Worker         PropagateError(CheckNormalizedTypes(RemoveConstFromTypes(Vector<Type<Rs>..., Ps...>)),
860*a65addddSAndroid Build Coastguard Worker                        PropagateError(CheckNoRequiredTypesInComponentArguments(Vector<Ps...>),
861*a65addddSAndroid Build Coastguard Worker                                       ConsComp(VectorToSetUnchecked(RemoveConstFromTypes(Vector<Type<Rs>...>)),
862*a65addddSAndroid Build Coastguard Worker                                                VectorToSetUnchecked(RemoveConstFromTypes(Vector<Ps...>)),
863*a65addddSAndroid Build Coastguard Worker                                                RemoveConstTypes(Vector<Type<Rs>..., Ps...>),
864*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
865*a65addddSAndroid Build Coastguard Worker                                                Vector<Pair<Ps, Vector<Type<Rs>...>>...>,
866*a65addddSAndroid Build Coastguard Worker #endif
867*a65addddSAndroid Build Coastguard Worker                                                Vector<>, EmptyList))));
868*a65addddSAndroid Build Coastguard Worker 
869*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK && FRUIT_EXTRA_DEBUG
870*a65addddSAndroid Build Coastguard Worker     using Loop = ProofForestFindLoop(GetComponentDeps(type1));
871*a65addddSAndroid Build Coastguard Worker     using type = If(IsNone(Loop), type1, ConstructErrorWithArgVector(SelfLoopErrorTag, Loop));
872*a65addddSAndroid Build Coastguard Worker #else  // FRUIT_NO_LOOP_CHECK || !FRUIT_EXTRA_DEBUG
873*a65addddSAndroid Build Coastguard Worker     using type = type1;
874*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_NO_LOOP_CHECK || !FRUIT_EXTRA_DEBUG
875*a65addddSAndroid Build Coastguard Worker   };
876*a65addddSAndroid Build Coastguard Worker };
877*a65addddSAndroid Build Coastguard Worker 
878*a65addddSAndroid Build Coastguard Worker struct CheckTypesNotProvidedAsConst {
879*a65addddSAndroid Build Coastguard Worker   template <typename Comp, typename V>
880*a65addddSAndroid Build Coastguard Worker   struct apply {
881*a65addddSAndroid Build Coastguard Worker     struct Helper {
882*a65addddSAndroid Build Coastguard Worker       template <typename Acc, typename T>
883*a65addddSAndroid Build Coastguard Worker       struct apply {
884*a65addddSAndroid Build Coastguard Worker         using type = If(And(IsInSet(T, typename Comp::Ps), Not(IsInSet(T, typename Comp::NonConstRsPs))),
885*a65addddSAndroid Build Coastguard Worker                         ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, T), Acc);
886*a65addddSAndroid Build Coastguard Worker       };
887*a65addddSAndroid Build Coastguard Worker     };
888*a65addddSAndroid Build Coastguard Worker 
889*a65addddSAndroid Build Coastguard Worker     using type = FoldVector(V, Helper, None);
890*a65addddSAndroid Build Coastguard Worker   };
891*a65addddSAndroid Build Coastguard Worker };
892*a65addddSAndroid Build Coastguard Worker 
893*a65addddSAndroid Build Coastguard Worker // Adds the types in NewRequirementsVector to the requirements (unless they are already provided/required).
894*a65addddSAndroid Build Coastguard Worker // The caller must convert the types to the corresponding class type and expand any Provider<>s.
895*a65addddSAndroid Build Coastguard Worker struct AddRequirements {
896*a65addddSAndroid Build Coastguard Worker   template <typename Comp, typename NewRequirementsVector, typename NewNonConstRequirementsVector>
897*a65addddSAndroid Build Coastguard Worker   struct apply {
898*a65addddSAndroid Build Coastguard Worker     using Comp1 = ConsComp(FoldVector(NewRequirementsVector, AddToSet, typename Comp::RsSuperset), typename Comp::Ps,
899*a65addddSAndroid Build Coastguard Worker                            FoldVector(NewNonConstRequirementsVector, AddToSet, typename Comp::NonConstRsPs),
900*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
901*a65addddSAndroid Build Coastguard Worker                            typename Comp::Deps,
902*a65addddSAndroid Build Coastguard Worker #endif
903*a65addddSAndroid Build Coastguard Worker                            typename Comp::InterfaceBindings, typename Comp::DeferredBindingFunctors);
904*a65addddSAndroid Build Coastguard Worker     using type = PropagateError(CheckTypesNotProvidedAsConst(Comp, NewNonConstRequirementsVector), Comp1);
905*a65addddSAndroid Build Coastguard Worker   };
906*a65addddSAndroid Build Coastguard Worker };
907*a65addddSAndroid Build Coastguard Worker 
908*a65addddSAndroid Build Coastguard Worker // Similar to AddProvidedType, but doesn't report an error if a Bind<C, CImpl> was present.
909*a65addddSAndroid Build Coastguard Worker struct AddProvidedTypeIgnoringInterfaceBindings {
910*a65addddSAndroid Build Coastguard Worker   template <typename Comp, typename C, typename IsNonConst, typename CRequirements, typename CNonConstRequirements>
911*a65addddSAndroid Build Coastguard Worker   struct apply {
912*a65addddSAndroid Build Coastguard Worker     using Comp1 = ConsComp(
913*a65addddSAndroid Build Coastguard Worker         FoldVector(CRequirements, AddToSet, typename Comp::RsSuperset), AddToSetUnchecked(typename Comp::Ps, C),
914*a65addddSAndroid Build Coastguard Worker         If(IsNonConst, AddToSetUnchecked(FoldVector(CNonConstRequirements, AddToSet, typename Comp::NonConstRsPs), C),
915*a65addddSAndroid Build Coastguard Worker            FoldVector(CNonConstRequirements, AddToSet, typename Comp::NonConstRsPs)),
916*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
917*a65addddSAndroid Build Coastguard Worker         PushFront(typename Comp::Deps, Pair<C, CRequirements>),
918*a65addddSAndroid Build Coastguard Worker #endif
919*a65addddSAndroid Build Coastguard Worker         typename Comp::InterfaceBindings, typename Comp::DeferredBindingFunctors);
920*a65addddSAndroid Build Coastguard Worker     using type = If(IsInSet(C, typename Comp::Ps), ConstructError(TypeAlreadyBoundErrorTag, C),
921*a65addddSAndroid Build Coastguard Worker                     PropagateError(CheckTypesNotProvidedAsConst(Comp, CNonConstRequirements), Comp1));
922*a65addddSAndroid Build Coastguard Worker   };
923*a65addddSAndroid Build Coastguard Worker };
924*a65addddSAndroid Build Coastguard Worker 
925*a65addddSAndroid Build Coastguard Worker // Adds C to the provides and removes it from the requirements (if it was there at all).
926*a65addddSAndroid Build Coastguard Worker // Also checks that it wasn't already provided.
927*a65addddSAndroid Build Coastguard Worker // Moreover, adds the requirements of C to the requirements, unless they were already provided/required.
928*a65addddSAndroid Build Coastguard Worker // The caller must convert the types to the corresponding class type and expand any Provider<>s.
929*a65addddSAndroid Build Coastguard Worker struct AddProvidedType {
930*a65addddSAndroid Build Coastguard Worker   template <typename Comp, typename C, typename IsNonConst, typename CRequirements, typename CNonConstRequirements>
931*a65addddSAndroid Build Coastguard Worker   struct apply {
932*a65addddSAndroid Build Coastguard Worker     using type = If(Not(IsNone(FindInMap(typename Comp::InterfaceBindings, C))),
933*a65addddSAndroid Build Coastguard Worker                     ConstructError(TypeAlreadyBoundErrorTag, C),
934*a65addddSAndroid Build Coastguard Worker                     AddProvidedTypeIgnoringInterfaceBindings(Comp, C, IsNonConst, CRequirements,
935*a65addddSAndroid Build Coastguard Worker                                                              CNonConstRequirements));
936*a65addddSAndroid Build Coastguard Worker   };
937*a65addddSAndroid Build Coastguard Worker };
938*a65addddSAndroid Build Coastguard Worker 
939*a65addddSAndroid Build Coastguard Worker struct AddDeferredBinding {
940*a65addddSAndroid Build Coastguard Worker   template <typename Comp, typename DeferredBinding>
941*a65addddSAndroid Build Coastguard Worker   struct apply {
942*a65addddSAndroid Build Coastguard Worker     using new_DeferredBindingFunctors = Cons<DeferredBinding, typename Comp::DeferredBindingFunctors>;
943*a65addddSAndroid Build Coastguard Worker     using type = ConsComp(typename Comp::RsSuperset, typename Comp::Ps, typename Comp::NonConstRsPs,
944*a65addddSAndroid Build Coastguard Worker #if !FRUIT_NO_LOOP_CHECK
945*a65addddSAndroid Build Coastguard Worker                           typename Comp::Deps,
946*a65addddSAndroid Build Coastguard Worker #endif
947*a65addddSAndroid Build Coastguard Worker                           typename Comp::InterfaceBindings, new_DeferredBindingFunctors);
948*a65addddSAndroid Build Coastguard Worker   };
949*a65addddSAndroid Build Coastguard Worker };
950*a65addddSAndroid Build Coastguard Worker 
951*a65addddSAndroid Build Coastguard Worker struct CheckNoLoopInDeps {
952*a65addddSAndroid Build Coastguard Worker   template <typename Comp>
953*a65addddSAndroid Build Coastguard Worker   struct apply {
954*a65addddSAndroid Build Coastguard Worker     using Loop = ProofForestFindLoop(typename Comp::Deps);
955*a65addddSAndroid Build Coastguard Worker     using type = If(IsNone(Loop), Bool<true>, ConstructErrorWithArgVector(SelfLoopErrorTag, Loop));
956*a65addddSAndroid Build Coastguard Worker   };
957*a65addddSAndroid Build Coastguard Worker };
958*a65addddSAndroid Build Coastguard Worker 
959*a65addddSAndroid Build Coastguard Worker #if FRUIT_EXTRA_DEBUG || FRUIT_IN_META_TEST
960*a65addddSAndroid Build Coastguard Worker struct CheckComponentEntails {
961*a65addddSAndroid Build Coastguard Worker   template <typename Comp, typename EntailedComp>
962*a65addddSAndroid Build Coastguard Worker   struct apply {
963*a65addddSAndroid Build Coastguard Worker     using CompRs = SetDifference(typename Comp::RsSuperset, typename Comp::Ps);
964*a65addddSAndroid Build Coastguard Worker     using EntailedCompRs = SetDifference(typename EntailedComp::RsSuperset, typename EntailedComp::Ps);
965*a65addddSAndroid Build Coastguard Worker     using CommonRs = SetIntersection(CompRs, EntailedCompRs);
966*a65addddSAndroid Build Coastguard Worker     using CommonPs = SetIntersection(typename Comp::Ps, typename EntailedComp::Ps);
967*a65addddSAndroid Build Coastguard Worker     using type =
968*a65addddSAndroid Build Coastguard Worker         If(Not(IsContained(typename EntailedComp::Ps, typename Comp::Ps)),
969*a65addddSAndroid Build Coastguard Worker            ConstructErrorWithArgVector(ComponentDoesNotEntailDueToProvidesErrorTag,
970*a65addddSAndroid Build Coastguard Worker                                        SetToVector(SetDifference(typename EntailedComp::Ps, typename Comp::Ps))),
971*a65addddSAndroid Build Coastguard Worker            If(Not(IsVectorContained(typename EntailedComp::InterfaceBindings, typename Comp::InterfaceBindings)),
972*a65addddSAndroid Build Coastguard Worker               ConstructErrorWithArgVector(ComponentDoesNotEntailDueToInterfaceBindingsErrorTag,
973*a65addddSAndroid Build Coastguard Worker                                           SetToVector(SetDifference(typename EntailedComp::InterfaceBindings,
974*a65addddSAndroid Build Coastguard Worker                                                                     typename Comp::InterfaceBindings))),
975*a65addddSAndroid Build Coastguard Worker               If(Not(IsContained(CompRs, EntailedCompRs)),
976*a65addddSAndroid Build Coastguard Worker                  ConstructErrorWithArgVector(ComponentDoesNotEntailDueToRequirementsErrorTag,
977*a65addddSAndroid Build Coastguard Worker                                              SetToVector(SetDifference(CompRs, EntailedCompRs))),
978*a65addddSAndroid Build Coastguard Worker                  If(Not(IsContained(SetIntersection(CommonRs, typename Comp::NonConstRsPs),
979*a65addddSAndroid Build Coastguard Worker                                     typename EntailedComp::NonConstRsPs)),
980*a65addddSAndroid Build Coastguard Worker                     ConstructErrorWithArgVector(ComponentDoesNotEntailDueToDifferentConstnessOfRequirementsErrorTag,
981*a65addddSAndroid Build Coastguard Worker                                                 SetToVector(SetDifference(SetIntersection(CommonRs,
982*a65addddSAndroid Build Coastguard Worker                                                                                           typename Comp::NonConstRsPs),
983*a65addddSAndroid Build Coastguard Worker                                                                           typename EntailedComp::NonConstRsPs))),
984*a65addddSAndroid Build Coastguard Worker                     If(Not(IsContained(SetIntersection(CommonPs, typename EntailedComp::NonConstRsPs),
985*a65addddSAndroid Build Coastguard Worker                                        typename Comp::NonConstRsPs)),
986*a65addddSAndroid Build Coastguard Worker                        ConstructErrorWithArgVector(
987*a65addddSAndroid Build Coastguard Worker                            ComponentDoesNotEntailDueToDifferentConstnessOfProvidesErrorTag,
988*a65addddSAndroid Build Coastguard Worker                            SetToVector(SetDifference(SetIntersection(CommonPs, typename EntailedComp::NonConstRsPs),
989*a65addddSAndroid Build Coastguard Worker                                                      typename Comp::NonConstRsPs))),
990*a65addddSAndroid Build Coastguard Worker                        Bool<true>)))));
991*a65addddSAndroid Build Coastguard Worker     static_assert(true || sizeof(typename CheckIfError<Eval<type>>::type), "");
992*a65addddSAndroid Build Coastguard Worker   };
993*a65addddSAndroid Build Coastguard Worker };
994*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_EXTRA_DEBUG || FRUIT_IN_META_TEST
995*a65addddSAndroid Build Coastguard Worker 
996*a65addddSAndroid Build Coastguard Worker // This calls ConstructError(NoBindingFoundErrorTag, ...) or
997*a65addddSAndroid Build Coastguard Worker // ConstructError(NoBindingFoundForAbstractClassErrorTag, ...) as appropriate.
998*a65addddSAndroid Build Coastguard Worker // Call this when we're unable to auto-inject a type AnnotatedC and we're giving up.
999*a65addddSAndroid Build Coastguard Worker struct ConstructNoBindingFoundError {
1000*a65addddSAndroid Build Coastguard Worker   template <typename AnnotatedC>
1001*a65addddSAndroid Build Coastguard Worker   struct apply {
1002*a65addddSAndroid Build Coastguard Worker     using type = If(IsAbstract(RemoveAnnotations(AnnotatedC)),
1003*a65addddSAndroid Build Coastguard Worker                     ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedC, RemoveAnnotations(AnnotatedC)),
1004*a65addddSAndroid Build Coastguard Worker                     ConstructError(NoBindingFoundErrorTag, AnnotatedC));
1005*a65addddSAndroid Build Coastguard Worker   };
1006*a65addddSAndroid Build Coastguard Worker };
1007*a65addddSAndroid Build Coastguard Worker 
1008*a65addddSAndroid Build Coastguard Worker } // namespace meta
1009*a65addddSAndroid Build Coastguard Worker } // namespace impl
1010*a65addddSAndroid Build Coastguard Worker } // namespace fruit
1011*a65addddSAndroid Build Coastguard Worker 
1012*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_META_COMPONENT_H
1013