xref: /aosp_15_r20/external/google-fruit/include/fruit/impl/component_functors.defn.h (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1 /*
2  * Copyright 2014 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef FRUIT_COMPONENT_FUNCTORS_DEFN_H
18 #define FRUIT_COMPONENT_FUNCTORS_DEFN_H
19 
20 #include <fruit/component.h>
21 
22 #include <fruit/impl/injection_debug_errors.h>
23 #include <fruit/impl/injection_errors.h>
24 #include <fruit/impl/injector/injector_storage.h>
25 
26 #include <memory>
27 
28 /*********************************************************************************************************************************
29   This file contains functors that take a Comp and return a struct Op with the form:
30   struct {
31     using Result = Comp1;
32     void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {...}
33     std::size_t numEntries() {...}
34   }
35 *********************************************************************************************************************************/
36 
37 namespace fruit {
38 namespace impl {
39 namespace meta {
40 
41 struct GetResult {
42   template <typename F>
43   struct apply {
44     using type = typename F::Result;
45   };
46 };
47 
48 // Call(ComponentFunctor(F, Args...), Comp)
49 // is equivalent to:
50 // F(Comp, Args...)
51 struct ComponentFunctor {
52   template <typename F, typename... Args>
53   struct apply {
54     struct type {
55       template <typename Comp>
56       struct apply {
57         using type = F(Comp, Args...);
58       };
59     };
60   };
61 };
62 
63 struct ComponentFunctorIdentity {
64   template <typename Comp>
65   struct apply {
66     struct type {
67       using Result = Comp;
operatorComponentFunctorIdentity::apply::type68       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
numEntriesComponentFunctorIdentity::apply::type69       std::size_t numEntries() {
70         return 0;
71       }
72     };
73   };
74 };
75 
76 struct Compose2ComponentFunctors {
77   template <typename F1, typename F2>
78   struct apply {
79     struct type {
80       template <typename Comp>
81       struct apply {
82         using Op1 = F1(Comp);
83         using Op2 = F2(GetResult(Op1));
84         struct Op {
85           using Result = Eval<GetResult(Op2)>;
operatorCompose2ComponentFunctors::apply::type::apply::Op86           void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
87             Eval<Op2>()(entries);
88             Eval<Op1>()(entries);
89           }
numEntriesCompose2ComponentFunctors::apply::type::apply::Op90           std::size_t numEntries() {
91             return Eval<Op1>().numEntries() + Eval<Op2>().numEntries();
92           }
93         };
94         using type = PropagateError(Op1, PropagateError(Op2, Op));
95       };
96     };
97   };
98 };
99 
100 // ComposeFunctors(F1,..,Fn) returns a functor that executes F1,..,Fn in order (stopping at the
101 // first Error).
102 struct ComposeFunctors {
103   template <typename... Functors>
104   struct apply {
105     using type = Fold(Compose2ComponentFunctors, ComponentFunctorIdentity, Functors...);
106   };
107 };
108 
109 // ReverseComposeFunctors(T1, ..., Tn) is equivalent to ComposeFunctors(Tn, ..., T1), but it's more
110 // efficient when all of the following must be evaluated:
111 // ReverseComposeFunctors<T1>
112 // ReverseComposeFunctors<T2, T1>
113 // ReverseComposeFunctors<T3, T2, T1>
114 // In that case, this implementation shares many more instantiations with previous invocations
115 struct ReverseComposeFunctors {
116   template <typename... Functors>
117   struct apply {
118     using type = ComponentFunctorIdentity;
119   };
120 
121   template <typename Functor>
122   struct apply<Functor> {
123     using type = Functor;
124   };
125 
126   template <typename Functor, typename... Functors>
127   struct apply<Functor, Functors...> {
128     using type = Compose2ComponentFunctors(ReverseComposeFunctors(Functors...), Functor);
129   };
130 };
131 
132 struct EnsureProvidedType;
133 
134 struct EnsureProvidedTypes;
135 
136 // Doesn't actually bind in ComponentStorage. The binding is added later (if needed) using ProcessInterfaceBinding.
137 struct AddDeferredInterfaceBinding {
138   template <typename Comp, typename AnnotatedI, typename AnnotatedC>
139   struct apply {
140     using Comp1 = ConsComp(typename Comp::RsSuperset, typename Comp::Ps, typename Comp::NonConstRsPs,
141 #if !FRUIT_NO_LOOP_CHECK
142                            typename Comp::Deps,
143 #endif
144                            PushFront(typename Comp::InterfaceBindings, Pair<AnnotatedI, AnnotatedC>),
145                            typename Comp::DeferredBindingFunctors);
146     struct Op {
147       // Note that we do NOT call AddProvidedType here. We'll only know the right required type
148       // when the binding will be used.
149       using Result = Eval<Comp1>;
150       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
151       std::size_t numEntries() {
152         return 0;
153       }
154     };
155     using I = RemoveAnnotations(AnnotatedI);
156     using C = RemoveAnnotations(AnnotatedC);
157     using type =
158         If(IsSame(I, C), ConstructError(InterfaceBindingToSelfErrorTag, C),
159            If(Not(IsBaseOf(I, C)), ConstructError(NotABaseClassOfErrorTag, I, C),
160               If(Not(IsSame(I, NormalizeType(I))), ConstructError(NonClassTypeErrorTag, I, NormalizeUntilStable(I)),
161                  If(Not(IsSame(C, NormalizeType(C))),
162                     // We handle this case too, just to be on the safe side, but this should never happen.
163                     ConstructError(NonClassTypeErrorTag, C, NormalizeUntilStable(C)),
164                     If(IsInSet(AnnotatedI, typename Comp::Ps), ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI),
165                        If(MapContainsKey(typename Comp::InterfaceBindings, AnnotatedI),
166                           ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI), Op))))));
167   };
168 };
169 
170 struct ProcessInterfaceBinding {
171   template <typename Comp, typename AnnotatedI, typename AnnotatedC, typename NonConstBindingRequired>
172   struct apply {
173     using R = If(NonConstBindingRequired,
174                  AddProvidedTypeIgnoringInterfaceBindings(Comp, AnnotatedI, NonConstBindingRequired, Vector<AnnotatedC>,
175                                                           Vector<AnnotatedC>),
176                  AddProvidedTypeIgnoringInterfaceBindings(Comp, AnnotatedI, NonConstBindingRequired, Vector<AnnotatedC>,
177                                                           Vector<>));
178     struct ConstOp {
179       // This must be here (and not in AddDeferredInterfaceBinding) because the binding might be
180       // used to bind functors instead, so we might never need to add C to the requirements.
181       using Result = Eval<R>;
182       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
183         entries.push_back(
184             InjectorStorage::createComponentStorageEntryForConstBind<UnwrapType<AnnotatedI>, UnwrapType<AnnotatedC>>());
185       };
186 
187       std::size_t numEntries() {
188         return 1;
189       }
190     };
191     struct NonConstOp {
192       // This must be here (and not in AddDeferredInterfaceBinding) because the binding might be
193       // used to bind functors instead, so we might never need to add C to the requirements.
194       using Result = Eval<R>;
195       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
196         entries.push_back(
197             InjectorStorage::createComponentStorageEntryForBind<UnwrapType<AnnotatedI>, UnwrapType<AnnotatedC>>());
198       };
199 
200       std::size_t numEntries() {
201         return 1;
202       }
203     };
204     using type = PropagateError(R, If(NonConstBindingRequired, NonConstOp, ConstOp));
205   };
206 };
207 
208 struct AddInterfaceMultibinding {
209   template <typename Comp, typename AnnotatedI, typename AnnotatedC>
210   struct apply {
211     using I = RemoveAnnotations(AnnotatedI);
212     using C = RemoveAnnotations(AnnotatedC);
213     using R = AddRequirements(Comp, Vector<AnnotatedC>, Vector<AnnotatedC>);
214     struct Op {
215       using Result = Eval<R>;
216       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
217         entries.push_back(InjectorStorage::createComponentStorageEntryForMultibinding<UnwrapType<AnnotatedI>,
218                                                                                       UnwrapType<AnnotatedC>>());
219         entries.push_back(
220             InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator<UnwrapType<AnnotatedI>>());
221       };
222 
223       std::size_t numEntries() {
224         return 2;
225       }
226     };
227     using type = If(Not(IsBaseOf(I, C)), ConstructError(NotABaseClassOfErrorTag, I, C), Op);
228   };
229 };
230 
231 template <typename AnnotatedSignature, typename Lambda, typename OptionalAnnotatedI>
232 struct PostProcessRegisterProviderHelper;
233 
234 template <typename AnnotatedSignature, typename Lambda, typename AnnotatedI>
235 struct PostProcessRegisterProviderHelper;
236 
237 template <typename AnnotatedSignature, typename Lambda, typename AnnotatedI>
238 struct PostProcessRegisterProviderHelper<AnnotatedSignature, Lambda, Type<AnnotatedI>> {
239   inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
240     entries.push_back(
241         InjectorStorage::createComponentStorageEntryForCompressedProvider<AnnotatedSignature, Lambda, AnnotatedI>());
242     entries.push_back(InjectorStorage::createComponentStorageEntryForProvider<AnnotatedSignature, Lambda>());
243   }
244 
245   std::size_t numEntries() {
246     return 2;
247   }
248 };
249 
250 template <typename AnnotatedSignature, typename Lambda>
251 struct PostProcessRegisterProviderHelper<AnnotatedSignature, Lambda, None> {
252   inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
253     entries.push_back(InjectorStorage::createComponentStorageEntryForProvider<AnnotatedSignature, Lambda>());
254   }
255 
256   std::size_t numEntries() {
257     return 1;
258   }
259 };
260 
261 // T can't be any injectable type, it must match the return type of the provider in one of
262 // the registerProvider() overloads in ComponentStorage.
263 struct PostProcessRegisterProvider {
264   template <typename Comp, typename AnnotatedSignature, typename Lambda>
265   struct apply {
266     using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
267     using OptionalAnnotatedI = FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC);
268     struct Op {
269       using Result = Comp;
270 
271       using Helper = PostProcessRegisterProviderHelper<UnwrapType<AnnotatedSignature>, UnwrapType<Lambda>,
272                                                        Eval<OptionalAnnotatedI>>;
273       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
274         Helper()(entries);
275       }
276       std::size_t numEntries() {
277         return Helper().numEntries();
278       }
279     };
280     using type = Op;
281   };
282 };
283 
284 struct PreProcessRegisterProvider {
285   template <typename Comp, typename AnnotatedSignature, typename Lambda>
286   struct apply {
287     using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
288     using SignatureFromLambda = FunctionSignature(Lambda);
289 
290     using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
291     using AnnotatedCDeps = NormalizeTypeVector(SignatureArgs(AnnotatedSignature));
292     using R = AddProvidedType(Comp, AnnotatedC, Bool<true>, AnnotatedCDeps,
293                               Id<NormalizedNonConstTypesIn(SignatureArgs(AnnotatedSignature))>);
294     using type =
295         If(Not(IsSame(Signature, SignatureFromLambda)),
296            ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature, SignatureFromLambda),
297            PropagateError(
298                CheckInjectableType(RemoveAnnotations(SignatureType(AnnotatedSignature))),
299                PropagateError(
300                    CheckInjectableTypeVector(RemoveAnnotationsFromVector(AnnotatedCDeps)),
301                    PropagateError(
302                        CheckInjectableType(SignatureType(SignatureFromLambda)),
303                        PropagateError(
304                            CheckInjectableTypeVector(SignatureArgs(SignatureFromLambda)),
305                            If(And(IsPointer(SignatureType(SignatureFromLambda)),
306                                   And(IsAbstract(RemovePointer(SignatureType(SignatureFromLambda))),
307                                       Not(HasVirtualDestructor(RemovePointer(SignatureType(SignatureFromLambda)))))),
308                               ConstructError(ProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag,
309                                              RemovePointer(SignatureType(SignatureFromLambda))),
310                               ComponentFunctorIdentity(R)))))));
311   };
312 };
313 
314 // The registration is actually deferred until the PartialComponent is converted to a component.
315 struct DeferredRegisterProviderWithAnnotations {
316   template <typename Comp, typename AnnotatedSignature, typename Lambda>
317   struct apply {
318     using Comp1 = AddDeferredBinding(Comp, ComponentFunctor(PostProcessRegisterProvider, AnnotatedSignature, Lambda));
319     using type = PreProcessRegisterProvider(Comp1, AnnotatedSignature, Lambda);
320   };
321 };
322 
323 // The registration is actually deferred until the PartialComponent is converted to a component.
324 struct DeferredRegisterProvider {
325   template <typename Comp, typename Lambda>
326   struct apply {
327     using type = DeferredRegisterProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda);
328   };
329 };
330 
331 // T can't be any injectable type, it must match the return type of the provider in one of
332 // the registerMultibindingProvider() overloads in ComponentStorage.
333 struct RegisterMultibindingProviderWithAnnotations {
334   template <typename Comp, typename AnnotatedSignature, typename Lambda>
335   struct apply {
336     using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
337     using SignatureFromLambda = FunctionSignature(Lambda);
338 
339     using AnnotatedArgs = SignatureArgs(AnnotatedSignature);
340     using AnnotatedArgVector = NormalizeTypeVector(AnnotatedArgs);
341     using NonConstRequirements = NormalizedNonConstTypesIn(AnnotatedArgs);
342     using R = AddRequirements(Comp, AnnotatedArgVector, NonConstRequirements);
343     struct Op {
344       using Result = Eval<R>;
345       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
346         entries.push_back(
347             InjectorStorage::createComponentStorageEntryForMultibindingProvider<UnwrapType<AnnotatedSignature>,
348                                                                                 UnwrapType<Lambda>>());
349         entries.push_back(InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator<
350                           UnwrapType<Eval<NormalizeType(SignatureType(AnnotatedSignature))>>>());
351       }
352       std::size_t numEntries() {
353         return 2;
354       }
355     };
356     using type = If(
357         Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature),
358         PropagateError(
359             CheckInjectableType(RemoveAnnotations(SignatureType(AnnotatedSignature))),
360             PropagateError(
361                 CheckInjectableTypeVector(RemoveAnnotationsFromVector(SignatureArgs(AnnotatedSignature))),
362                 PropagateError(
363                     CheckInjectableType(SignatureType(SignatureFromLambda)),
364                     PropagateError(
365                         CheckInjectableTypeVector(SignatureArgs(SignatureFromLambda)),
366                         If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))),
367                            ConstructError(CannotConstructAbstractClassErrorTag,
368                                           RemoveAnnotations(SignatureType(AnnotatedSignature))),
369                            If(Not(IsSame(Signature, SignatureFromLambda)),
370                               ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature,
371                                              SignatureFromLambda),
372                               If(And(IsPointer(SignatureType(SignatureFromLambda)),
373                                      And(IsAbstract(RemovePointer(SignatureType(SignatureFromLambda))),
374                                          Not(HasVirtualDestructor(RemovePointer(SignatureType(SignatureFromLambda)))))),
375                                  ConstructError(
376                                      MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag,
377                                      RemovePointer(SignatureType(SignatureFromLambda))),
378                                  PropagateError(R, Op)))))))));
379   };
380 };
381 
382 // T can't be any injectable type, it must match the return type of the provider in one of
383 // the registerMultibindingProvider() overloads in ComponentStorage.
384 struct RegisterMultibindingProvider {
385   template <typename Comp, typename Lambda>
386   struct apply {
387     using type = RegisterMultibindingProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda);
388   };
389 };
390 
391 // Non-assisted case.
392 template <int numAssistedBefore, int numNonAssistedBefore, typename Arg>
393 struct GetAssistedArg {
394   template <typename InjectedArgsTuple, typename UserProvidedArgsTuple>
395   inline Arg operator()(InjectedArgsTuple& injected_args, UserProvidedArgsTuple&) {
396     return std::get<numNonAssistedBefore>(injected_args);
397   }
398 };
399 
400 // Assisted case.
401 template <int numAssistedBefore, int numNonAssistedBefore, typename Arg>
402 struct GetAssistedArg<numAssistedBefore, numNonAssistedBefore, Assisted<Arg>> {
403   template <typename InjectedArgsTuple, typename UserProvidedArgsTuple>
404   inline Arg operator()(InjectedArgsTuple&, UserProvidedArgsTuple& user_provided_args) {
405     return std::forward<typename std::tuple_element<numAssistedBefore, UserProvidedArgsTuple>::type>(std::get<numAssistedBefore>(user_provided_args));
406   }
407 };
408 
409 struct RegisterFactoryHelper {
410 
411   template <typename Comp, typename DecoratedSignature, typename Lambda,
412             // std::function<InjectedSignature> is the injected type (possibly with an Annotation<> wrapping it)
413             typename InjectedSignature, typename RequiredLambdaSignature, typename InjectedAnnotatedArgs,
414             // The types that are injected, unwrapped from any Annotation<>.
415             typename InjectedArgs, typename IndexSequence>
416   struct apply;
417 
418   template <typename Comp, typename DecoratedSignature, typename Lambda, typename NakedC,
419             typename... NakedUserProvidedArgs, typename... NakedAllArgs, typename... InjectedAnnotatedArgs,
420             typename... NakedInjectedArgs, typename... Indexes>
421   struct apply<Comp, DecoratedSignature, Lambda, Type<NakedC(NakedUserProvidedArgs...)>, Type<NakedC(NakedAllArgs...)>,
422                Vector<InjectedAnnotatedArgs...>, Vector<Type<NakedInjectedArgs>...>, Vector<Indexes...>> {
423     // Here we call "decorated" the types that might be wrapped in Annotated<> or Assisted<>,
424     // while we call "annotated" the ones that might only be wrapped in Annotated<> (but not Assisted<>).
425     using AnnotatedT = SignatureType(DecoratedSignature);
426     using T = RemoveAnnotations(AnnotatedT);
427     using DecoratedArgs = SignatureArgs(DecoratedSignature);
428     using NakedInjectedSignature = NakedC(NakedUserProvidedArgs...);
429     using NakedRequiredSignature = NakedC(NakedAllArgs...);
430     using NakedFunctor = std::function<NakedInjectedSignature>;
431     // This is usually the same as Functor, but this might be annotated.
432     using AnnotatedFunctor = CopyAnnotation(AnnotatedT, Type<NakedFunctor>);
433     using FunctorDeps = NormalizeTypeVector(Vector<InjectedAnnotatedArgs...>);
434     using FunctorNonConstDeps = NormalizedNonConstTypesIn(Vector<InjectedAnnotatedArgs...>);
435     using R = AddProvidedType(Comp, AnnotatedFunctor, Bool<true>, FunctorDeps, FunctorNonConstDeps);
436 
437     struct ObjectProvider {
438       std::tuple<NakedInjectedArgs...> injected_args;
439 
440       explicit ObjectProvider(std::tuple<NakedInjectedArgs...>&& injected_args) : injected_args(std::move(injected_args)) {}
441 
442       NakedC operator()(NakedUserProvidedArgs&&... params) {
443         auto user_provided_args = std::forward_as_tuple(std::forward<decltype(params)>(params)...);
444         // These are unused if they are 0-arg tuples. Silence the unused-variable warnings anyway.
445         (void)injected_args;
446         (void)user_provided_args;
447 
448         return LambdaInvoker::invoke<UnwrapType<Lambda>, NakedAllArgs...>(
449             GetAssistedArg<
450                 Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value,
451                 getIntValue<Indexes>() - Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value,
452                 // Note that the Assisted<> wrapper (if any) remains, we just remove any wrapping Annotated<>.
453                 UnwrapType<Eval<RemoveAnnotations(GetNthType(Indexes, DecoratedArgs))>>>()(injected_args,
454                                                                                            user_provided_args)...);
455       }
456     };
457 
458     struct Op {
459       using Result = Eval<R>;
460       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
461         auto function_provider = [](NakedInjectedArgs... args) {
462           return NakedFunctor{ObjectProvider{std::tuple<NakedInjectedArgs...>{args...}}};
463         };
464         (void)function_provider;
465         entries.push_back(InjectorStorage::createComponentStorageEntryForProvider<
466                           UnwrapType<Eval<ConsSignatureWithVector(AnnotatedFunctor, Vector<InjectedAnnotatedArgs...>)>>,
467                           decltype(function_provider)>());
468       }
469       std::size_t numEntries() {
470         return 1;
471       }
472     };
473     // The first two IsValidSignature checks are a bit of a hack, they are needed to make the F2/RealF2 split
474     // work in the caller (we need to allow Lambda to be a function type).
475     using type = If(Not(IsSame(Type<NakedRequiredSignature>, FunctionSignature(Lambda))),
476                     ConstructError(FunctorSignatureDoesNotMatchErrorTag, Type<NakedRequiredSignature>,
477                                    FunctionSignature(Lambda)),
478                     If(IsPointer(T), ConstructError(FactoryReturningPointerErrorTag, DecoratedSignature),
479                        PropagateError(R, Op)));
480   };
481 };
482 
483 struct RegisterFactory {
484   template <typename Comp, typename DecoratedSignature, typename Lambda>
485   struct apply {
486     using LambdaReturnType = SignatureType(FunctionSignature(Lambda));
487     using type =
488         If(Not(IsValidSignature(DecoratedSignature)), ConstructError(NotASignatureErrorTag, DecoratedSignature),
489            PropagateError(
490                CheckInjectableType(RemoveAnnotations(SignatureType(DecoratedSignature))),
491                PropagateError(
492                    CheckInjectableTypeVector(
493                        RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature)))),
494                    If(IsAbstract(RemoveAnnotations(SignatureType(DecoratedSignature))),
495                       // We error out early in this case. Calling RegisterFactoryHelper would also produce an error, but
496                       // it'd be
497                       // much less user-friendly.
498                       ConstructError(CannotConstructAbstractClassErrorTag,
499                                      RemoveAnnotations(SignatureType(DecoratedSignature))),
500                       If(Not(Or(IsEmpty(Lambda), IsValidSignature(Lambda))),
501                          ConstructError(LambdaWithCapturesErrorTag, Lambda),
502                          If(Not(Or(IsTriviallyCopyable(Lambda), IsValidSignature(Lambda))),
503                             ConstructError(NonTriviallyCopyableLambdaErrorTag, Lambda),
504                             If(And(IsUniquePtr(LambdaReturnType),
505                                    And(IsAbstract(RemoveUniquePtr(LambdaReturnType)),
506                                        Not(HasVirtualDestructor(RemoveUniquePtr(LambdaReturnType))))),
507                                ConstructError(RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorErrorTag,
508                                               RemoveUniquePtr(LambdaReturnType)),
509                                RegisterFactoryHelper(
510                                    Comp, DecoratedSignature, Lambda,
511                                    InjectedSignatureForAssistedFactory(DecoratedSignature),
512                                    RequiredLambdaSignatureForAssistedFactory(DecoratedSignature),
513                                    RemoveAssisted(SignatureArgs(DecoratedSignature)),
514                                    RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature))),
515                                    GenerateIntSequence(
516                                        VectorSize(RequiredLambdaArgsForAssistedFactory(DecoratedSignature)))))))))));
517   };
518 };
519 
520 struct PostProcessRegisterConstructor;
521 
522 template <typename AnnotatedSignature, typename OptionalAnnotatedI>
523 struct PostProcessRegisterConstructorHelper;
524 
525 template <typename AnnotatedSignature, typename AnnotatedI>
526 struct PostProcessRegisterConstructorHelper;
527 
528 template <typename AnnotatedSignature, typename AnnotatedI>
529 struct PostProcessRegisterConstructorHelper<AnnotatedSignature, Type<AnnotatedI>> {
530   inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
531     entries.push_back(
532         InjectorStorage::createComponentStorageEntryForCompressedConstructor<AnnotatedSignature, AnnotatedI>());
533     entries.push_back(InjectorStorage::createComponentStorageEntryForConstructor<AnnotatedSignature>());
534   }
535   std::size_t numEntries() {
536     return 2;
537   }
538 };
539 
540 template <typename AnnotatedSignature>
541 struct PostProcessRegisterConstructorHelper<AnnotatedSignature, None> {
542   inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
543     entries.push_back(InjectorStorage::createComponentStorageEntryForConstructor<AnnotatedSignature>());
544   }
545   std::size_t numEntries() {
546     return 1;
547   }
548 };
549 
550 struct PostProcessRegisterConstructor {
551   template <typename Comp, typename AnnotatedSignature>
552   struct apply {
553     struct type {
554       using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
555       using Result = Comp;
556       using Helper =
557           PostProcessRegisterConstructorHelper<UnwrapType<AnnotatedSignature>,
558                                                Eval<FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC)>>;
559       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
560         Helper()(entries);
561       }
562       std::size_t numEntries() {
563         return Helper().numEntries();
564       }
565     };
566   };
567 };
568 
569 struct PreProcessRegisterConstructor {
570   template <typename Comp, typename AnnotatedSignature>
571   struct apply {
572     using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
573     using C = SignatureType(Signature);
574     using Args = SignatureArgs(Signature);
575     using AnnotatedT = SignatureType(AnnotatedSignature);
576     using AnnotatedArgs = SignatureArgs(AnnotatedSignature);
577     using AnnotatedC = NormalizeType(AnnotatedT);
578     using CDeps = NormalizeTypeVector(AnnotatedArgs);
579     using CNonConstDeps = NormalizedNonConstTypesIn(AnnotatedArgs);
580     using R = AddProvidedType(Comp, AnnotatedC, Bool<true>, CDeps, CNonConstDeps);
581     using type = If(Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature),
582         If(Not(IsSame(RemoveAssisted(Args), Args)), ConstructError(AssistedParamInRegisterConstructorSignatureErrorTag, AnnotatedSignature),
583         PropagateError(CheckInjectableType(RemoveAnnotations(C)),
584                        PropagateError(CheckInjectableTypeVector(RemoveAnnotationsFromVector(Args)),
585                                       If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))),
586                                          ConstructError(CannotConstructAbstractClassErrorTag,
587                                                         RemoveAnnotations(SignatureType(AnnotatedSignature))),
588                                          If(Not(IsConstructibleWithVector(C, Args)),
589                                             ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, Signature),
590                                             PropagateError(R, ComponentFunctorIdentity(R))))))));
591   };
592 };
593 
594 struct DeferredRegisterConstructor {
595   template <typename Comp, typename AnnotatedSignature>
596   struct apply {
597     using Comp1 = AddDeferredBinding(Comp, ComponentFunctor(PostProcessRegisterConstructor, AnnotatedSignature));
598     using type = PreProcessRegisterConstructor(Comp1, AnnotatedSignature);
599   };
600 };
601 
602 struct RegisterInstance {
603   template <typename Comp, typename AnnotatedC, typename C, typename IsNonConst>
604   struct apply {
605     using R = AddProvidedType(Comp, AnnotatedC, IsNonConst, Vector<>, Vector<>);
606     struct Op {
607       using Result = Eval<R>;
608       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
609       std::size_t numEntries() {
610         return 0;
611       }
612     };
613     using type = PropagateError(
614         CheckNormalizedTypes(ConsVector(RemoveAnnotations(AnnotatedC))),
615         PropagateError(
616             CheckNormalizedTypes(ConsVector(C)),
617             If(Not(IsSame(C, NormalizeType(C))), ConstructError(NonClassTypeErrorTag, C, NormalizeUntilStable(C)),
618                If(Not(IsSame(RemoveAnnotations(AnnotatedC), NormalizeType(RemoveAnnotations(AnnotatedC)))),
619                   ConstructError(NonClassTypeErrorTag, RemoveAnnotations(AnnotatedC),
620                                  NormalizeUntilStable(RemoveAnnotations(C))),
621                   // The IsSame check is not redundant because IsBaseOf returns false for non-class types (e.g. int).
622                   If(Not(Or(IsSame(RemoveAnnotations(AnnotatedC), C), IsBaseOf(RemoveAnnotations(AnnotatedC), C))),
623                      ConstructError(TypeMismatchInBindInstanceErrorTag, RemoveAnnotations(AnnotatedC), C),
624                      PropagateError(R, Op))))));
625   };
626 };
627 
628 struct RegisterConstructorAsValueFactory {
629   template <typename Comp, typename DecoratedSignature,
630             typename RequiredSignature = Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>>
631   struct apply;
632 
633   template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs>
634   struct apply<Comp, DecoratedSignature, Type<NakedT(NakedArgs...)>> {
635     using RequiredSignature = Type<NakedT(NakedArgs...)>;
636     using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature);
637     struct Op {
638       using Result = Eval<GetResult(Op1)>;
639       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
640         auto provider = [](NakedArgs... args) { return NakedT(std::forward<NakedArgs>(args)...); };
641         using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
642         FruitStaticAssert(IsSame(GetResult(Op1), GetResult(RealOp)));
643         Eval<RealOp>()(entries);
644       }
645       std::size_t numEntries() {
646 #if FRUIT_EXTRA_DEBUG
647         auto provider = [](NakedArgs... args) { return NakedT(std::forward<NakedArgs>(args)...); };
648         using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
649         FruitAssert(Eval<Op1>().numEntries() == Eval<RealOp>().numEntries());
650 #endif
651         return Eval<Op1>().numEntries();
652       }
653     };
654     using type = PropagateError(Op1, Op);
655   };
656 };
657 
658 struct RegisterConstructorAsUniquePtrFactory {
659   template <typename Comp, typename DecoratedSignature,
660             typename RequiredSignature = Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>>
661   struct apply;
662 
663   template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs>
664   struct apply<Comp, DecoratedSignature, Type<std::unique_ptr<NakedT>(NakedArgs...)>> {
665     using RequiredSignature = Type<std::unique_ptr<NakedT>(NakedArgs...)>;
666     using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature);
667     struct Op {
668       using Result = Eval<GetResult(Op1)>;
669       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
670         auto provider = [](NakedArgs... args) {
671           return std::unique_ptr<NakedT>(new NakedT(std::forward<NakedArgs>(args)...));
672         };
673         // Changed to typedef from a using declaration to workaround a bug in MSVC 2022.
674         typedef RegisterFactory RealOp(Comp, DecoratedSignature, Type<decltype(provider)>);
675         FruitStaticAssert(IsSame(GetResult(Op1), GetResult(RealOp)));
676         Eval<RealOp>()(entries);
677       };
678       std::size_t numEntries() {
679 #if FRUIT_EXTRA_DEBUG
680         auto provider = [](NakedArgs... args) {
681           return std::unique_ptr<NakedT>(new NakedT(std::forward<NakedArgs>(args)...));
682         };
683         using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
684         FruitAssert(Eval<Op1>().numEntries() == Eval<RealOp>().numEntries());
685 #endif
686         return Eval<Op1>().numEntries();
687       }
688     };
689 
690     using type = PropagateError(Op1, Op);
691   };
692 };
693 
694 struct InstallComponent {
695   template <typename Comp, typename OtherComp>
696   struct apply {
697     using new_RsSuperset = SetUnion(typename OtherComp::RsSuperset, typename Comp::RsSuperset);
698     using new_Ps = SetUncheckedUnion(typename OtherComp::Ps, typename Comp::Ps);
699     using new_NonConstRsPs = SetUnion(typename OtherComp::NonConstRsPs, typename Comp::NonConstRsPs);
700 #if !FRUIT_NO_LOOP_CHECK
701     using new_Deps = ConcatVectors(typename OtherComp::Deps, typename Comp::Deps);
702 #endif
703     FruitStaticAssert(IsSame(typename OtherComp::InterfaceBindings, Vector<>));
704     using new_InterfaceBindings = typename Comp::InterfaceBindings;
705 
706     FruitStaticAssert(IsSame(typename OtherComp::DeferredBindingFunctors, EmptyList));
707     using new_DeferredBindingFunctors = typename Comp::DeferredBindingFunctors;
708 
709     using R = ConsComp(new_RsSuperset, new_Ps, new_NonConstRsPs,
710 #if !FRUIT_NO_LOOP_CHECK
711                        new_Deps,
712 #endif
713                        new_InterfaceBindings, new_DeferredBindingFunctors);
714     struct Op {
715       using Result = Eval<R>;
716       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
717       std::size_t numEntries() {
718         return 0;
719       }
720     };
721     using InterfacePs = VectorToSetUnchecked(GetMapKeys(typename Comp::InterfaceBindings));
722     using AllPs = SetUncheckedUnion(InterfacePs, typename Comp::Ps);
723     using DuplicateTypes = SetIntersection(typename OtherComp::Ps, AllPs);
724     using CompConstPs = SetDifference(typename Comp::Ps, typename Comp::NonConstRsPs);
725     using CompRs = SetDifference(typename Comp::RsSuperset, typename Comp::Ps);
726     using CompNonConstRs = SetIntersection(CompRs, typename Comp::NonConstRsPs);
727 
728     using OtherCompConstPs = SetDifference(typename OtherComp::Ps, typename OtherComp::NonConstRsPs);
729     using OtherCompRs = SetDifference(typename OtherComp::RsSuperset, typename OtherComp::Ps);
730     using OtherCompNonConstRs = SetIntersection(OtherCompRs, typename OtherComp::NonConstRsPs);
731 
732     using type = If(Not(IsDisjoint(typename OtherComp::Ps, AllPs)),
733                     ConstructErrorWithArgVector(DuplicateTypesInComponentErrorTag, SetToVector(DuplicateTypes)),
734                     If(Not(IsDisjoint(CompConstPs, OtherCompNonConstRs)),
735                        ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag,
736                                       GetArbitrarySetElement(SetIntersection(CompConstPs, OtherCompNonConstRs))),
737                        If(Not(IsDisjoint(CompNonConstRs, OtherCompConstPs)),
738                           ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag,
739                                          GetArbitrarySetElement(SetIntersection(CompNonConstRs, OtherCompConstPs))),
740                           Op)));
741   };
742 };
743 
744 struct InstallComponentHelper {
745   template <typename Comp, typename... OtherCompParams>
746   struct apply {
747     using OtherComp = ConstructComponentImpl(OtherCompParams...);
748     using type = InstallComponent(Comp, OtherComp);
749   };
750 };
751 
752 struct InstallComponentFunctions {
753     template <typename Comp, typename... ComponentFunctions>
754     struct apply;
755 
756     template <typename Comp>
757     struct apply<Comp> {
758       using type = ComponentFunctorIdentity(Comp);
759     };
760 
761     template <typename Comp, typename... ComponentParams, typename... ComponentFunctionArgs, typename... ComponentFunctions>
762     struct apply<Comp, Type<fruit::ComponentFunction<fruit::Component<ComponentParams...>, ComponentFunctionArgs...>>, ComponentFunctions...> {
763       using type =
764           Call(
765               Compose2ComponentFunctors(
766                   ComponentFunctor(InstallComponent, ConstructComponentImpl(Type<ComponentParams>...)),
767                   ComponentFunctor(InstallComponentFunctions, ComponentFunctions...)),
768               Comp);
769     };
770 
771     template <typename Comp, typename T, typename... ComponentFunctions>
772     struct apply<Comp, T, ComponentFunctions...> {
773         using type = ConstructError(IncorrectArgTypePassedToInstallComponentFuntionsErrorTag, T);
774     };
775 };
776 
777 // CatchAll(PropagateError(Expr, Bool<false>), IsErrorExceptionHandler) evaluates to Bool<true> if Expr throws an error,
778 // and Bool<false> otherwise.
779 struct IsErrorExceptionHandler {
780   template <typename E>
781   struct apply {
782     using type = Bool<true>;
783   };
784 };
785 
786 struct ConvertComponent {
787   template <typename SourceComp, typename DestComp>
788   struct apply {
789     using SourcePs = typename SourceComp::Ps;
790     using DestPs = typename DestComp::Ps;
791     using SourceRs = SetDifference(typename SourceComp::RsSuperset, typename SourceComp::Ps);
792     using DestRs = SetDifference(typename DestComp::RsSuperset, typename DestComp::Ps);
793     using NonConstSourceRs = SetIntersection(SourceRs, typename SourceComp::NonConstRsPs);
794     using NonConstDestPs = SetIntersection(DestPs, typename DestComp::NonConstRsPs);
795     using NonConstDestRs = SetIntersection(DestRs, typename DestComp::NonConstRsPs);
796 
797     using ConstSourcePs = SetDifference(SourcePs, typename SourceComp::NonConstRsPs);
798     using ConstDestRs = SetDifference(DestRs, typename DestComp::NonConstRsPs);
799 
800     // We need to register:
801     // * All the types provided by the new component
802     // * All the types required by the old component
803     // except:
804     // * The ones already provided by the old component (if they have the right constness).
805     // * The ones required by the new one (if they have the right constness).
806     using ToRegister = SetUnion(
807         // The types that we must provide and aren't currently provided
808         SetDifference(SetUnion(DestPs, SourceRs), SetUnion(DestRs, SourcePs)),
809         // And the ones that are currently provided as const but that we need to provide as non-const
810         SetIntersection(SetUnion(NonConstDestPs, NonConstSourceRs), SetUnion(ConstDestRs, ConstSourcePs)));
811     using NonConstTypesToRegister = SetIntersection(ToRegister, SetUnion(typename SourceComp::NonConstRsPs,
812                                                                          typename DestComp::NonConstRsPs));
813     using type = EnsureProvidedTypes(SourceComp, DestRs, NonConstDestRs, SetToVector(ToRegister),
814                                      NonConstTypesToRegister);
815 
816 // Not needed, just double-checking.
817 // Uses FruitStaticAssert instead of FruitDelegateCheck so that it's checked only in debug mode.
818 #if FRUIT_EXTRA_DEBUG
819     FruitDelegateCheck(
820         If(CatchAll(PropagateError(type, PropagateError(Id<GetResult(type)>, Bool<false>)), IsErrorExceptionHandler),
821            // We're going to return an error soon anyway, we don't want to interfere by reporting this one.
822            None, CheckComponentEntails(GetResult(type), DestComp)));
823 #endif // FRUIT_EXTRA_DEBUG
824   };
825 };
826 
827 struct ProcessDeferredBindings {
828   template <typename Comp>
829   struct apply;
830 
831   template <typename RsSupersetParam, typename PsParam, typename NonConstRsPsParam,
832 #if !FRUIT_NO_LOOP_CHECK
833             typename DepsParam,
834 #endif
835             typename InterfaceBindingsParam, typename DeferredBindingFunctors>
836   struct apply<Comp<RsSupersetParam, PsParam, NonConstRsPsParam,
837 #if !FRUIT_NO_LOOP_CHECK
838                     DepsParam,
839 #endif
840                     InterfaceBindingsParam, DeferredBindingFunctors>> {
841     // Comp1 is the same as Comp, but without the DeferredBindingFunctors.
842     using Comp1 = ConsComp(RsSupersetParam, PsParam, NonConstRsPsParam,
843 #if !FRUIT_NO_LOOP_CHECK
844                            DepsParam,
845 #endif
846                            InterfaceBindingsParam, EmptyList);
847     using type = Call(FoldList(DeferredBindingFunctors, Compose2ComponentFunctors, ComponentFunctorIdentity), Comp1);
848   };
849 };
850 
851 template <typename AnnotatedCFunctor, typename AnnotatedCUniquePtrFunctor>
852 struct AutoRegisterFactoryHelperErrorHandler {
853   template <typename E>
854   struct apply {
855     using type = E;
856   };
857 
858   template <typename T>
859   struct apply<Error<NoBindingFoundErrorTag, T>> {
860     using type = If(IsSame(Type<T>, AnnotatedCFunctor), ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor),
861                     ConstructError(NoBindingFoundErrorTag, Type<T>));
862   };
863 
864   template <typename T1, typename T2>
865   struct apply<Error<NoBindingFoundForAbstractClassErrorTag, T1, T2>> {
866     using type = If(IsSame(Type<T1>, AnnotatedCFunctor), ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor),
867                     ConstructError(NoBindingFoundForAbstractClassErrorTag, Type<T1>, Type<T2>));
868   };
869 };
870 
871 struct AutoRegisterFactoryHelper {
872 
873   // General case, no way to bind it.
874   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename InterfaceBinding,
875             typename has_inject_annotation, typename is_abstract, typename C, typename AnnotatedSignature,
876             typename... Args>
877   struct apply {
878     using AnnotatedC = SignatureType(AnnotatedSignature);
879     using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature));
880     using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
881     using type = If(IsAbstract(C), ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, C),
882                     ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor));
883   };
884 
885   // No way to bind it (we need this specialization too to ensure that the specialization below
886   // is not chosen for AnnotatedC=None).
887   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused1,
888             typename unused2, typename NakedI, typename AnnotatedSignature, typename... Args>
889   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, unused1, unused2,
890                Type<std::unique_ptr<NakedI>>, AnnotatedSignature, Args...> {
891     using AnnotatedC = SignatureType(AnnotatedSignature);
892     using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature));
893     using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
894     using type = If(IsAbstract(Type<NakedI>),
895                     ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, Type<NakedI>),
896                     ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor));
897   };
898 
899   // AnnotatedI has an interface binding, use it and look for a factory that returns the type that AnnotatedI is bound
900   // to.
901   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC,
902             typename unused1, typename unused2, typename NakedI, typename AnnotatedSignature, typename... Args>
903   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, AnnotatedC, unused1, unused2,
904                Type<std::unique_ptr<NakedI>>, AnnotatedSignature, Args...> {
905     using I = Type<NakedI>;
906     using AnnotatedI = CopyAnnotation(SignatureType(AnnotatedSignature), I);
907     using C = RemoveAnnotations(AnnotatedC);
908     using IFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(I), Args...));
909     using CFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...));
910     using AnnotatedIFunctor = CopyAnnotation(AnnotatedI, IFunctor);
911     using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
912 
913     using ProvidedSignature = ConsSignature(AnnotatedIFunctor,
914                                             CopyAnnotation(AnnotatedC, ConsConstReference(CFunctor)));
915     using LambdaSignature = ConsSignature(IFunctor, ConsConstReference(CFunctor));
916 
917     using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, AnnotatedCFunctor,
918                                 Bool<false>);
919     using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature);
920     using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature);
921     using R = Call(ComposeFunctors(F1, F2, F3), Comp);
922     struct Op {
923       using Result = Eval<GetResult(R)>;
924       using NakedC = UnwrapType<Eval<C>>;
925       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
926         auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) {
927           return UnwrapType<Eval<IFunctor>>([=](typename Args::type... args) {
928             NakedC* c = fun(args...).release();
929             NakedI* i = static_cast<NakedI*>(c);
930             return std::unique_ptr<NakedI>(i);
931           });
932         };
933         FruitStaticAssert(IsSame(
934             GetResult(
935                 Call(ComposeFunctors(
936                          F1,
937                          ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>),
938                          ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)),
939                      Comp)),
940             GetResult(R)));
941         Eval<Call(ComposeFunctors(
942                       F1,
943                       ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>),
944                       ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)),
945                   Comp)>()(entries);
946       }
947       std::size_t numEntries() {
948 #if FRUIT_EXTRA_DEBUG
949         auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) {
950           return UnwrapType<Eval<IFunctor>>([=](typename Args::type... args) {
951             NakedC* c = fun(args...).release();
952             NakedI* i = static_cast<NakedI*>(c);
953             return std::unique_ptr<NakedI>(i);
954           });
955         };
956         FruitAssert(
957             Eval<R>().numEntries() ==
958             Eval<Call(ComposeFunctors(
959                           F1, ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>),
960                           ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)),
961                       Comp)>()
962                 .numEntries());
963 #endif
964         return Eval<R>().numEntries();
965       }
966     };
967     using type = PropagateError(R, If(Not(HasVirtualDestructor(I)),
968                                       ConstructError(FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorErrorTag,
969                                                      IFunctor, CFunctor),
970                                       Op));
971   };
972 
973   // C doesn't have an interface binding as interface, nor an INJECT annotation, and is not an abstract class.
974   // Bind std::function<unique_ptr<C>(Args...)> to std::function<C(Args...)> (possibly with annotations).
975   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC,
976             typename AnnotatedSignature, typename... Args>
977   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<false>, Bool<false>,
978                Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> {
979     using C = Type<NakedC>;
980     using CFunctor = ConsStdFunction(ConsSignature(C, Args...));
981     using CUniquePtrFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...));
982     using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature);
983     using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, C);
984     using AnnotatedCFunctor = CopyAnnotation(AnnotatedCUniquePtr, CFunctor);
985     using AnnotatedCUniquePtrFunctor = CopyAnnotation(AnnotatedCUniquePtr, CUniquePtrFunctor);
986     using AnnotatedCFunctorRef = CopyAnnotation(AnnotatedCUniquePtr, ConsConstReference(CFunctor));
987 
988     using ProvidedSignature = ConsSignature(AnnotatedCUniquePtrFunctor, AnnotatedCFunctorRef);
989     using LambdaSignature = ConsSignature(CUniquePtrFunctor, ConsConstReference(CFunctor));
990 
991     using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, AnnotatedCFunctor,
992                                 Bool<false>);
993     using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature);
994     using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature);
995     using R = Call(ComposeFunctors(F1, F2, F3), Comp);
996     struct Op {
997       using Result = Eval<GetResult(R)>;
998       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
999         auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) {
1000           return UnwrapType<Eval<CUniquePtrFunctor>>([=](typename TypeUnwrapper<Args>::type... args) {
1001             NakedC* c = new NakedC(fun(args...));
1002             return std::unique_ptr<NakedC>(c);
1003           });
1004         };
1005         using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
1006         using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
1007         using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp);
1008         FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R)));
1009         Eval<RealOp>()(entries);
1010       }
1011       std::size_t numEntries() {
1012 #if FRUIT_EXTRA_DEBUG
1013         auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) {
1014           return UnwrapType<Eval<CUniquePtrFunctor>>([=](typename TypeUnwrapper<Args>::type... args) {
1015             NakedC* c = new NakedC(fun(args...));
1016             return std::unique_ptr<NakedC>(c);
1017           });
1018         };
1019         using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
1020         using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
1021         using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp);
1022         FruitAssert(Eval<R>().numEntries() == Eval<RealOp>().numEntries());
1023 #endif
1024         return Eval<R>().numEntries();
1025       }
1026     };
1027 
1028     using ErrorHandler =
1029         AutoRegisterFactoryHelperErrorHandler<Eval<AnnotatedCFunctor>, Eval<AnnotatedCUniquePtrFunctor>>;
1030 
1031     // If we are about to report a NoBindingFound/NoBindingFoundForAbstractClass error for AnnotatedCFunctor,
1032     // report one for std::function<std::unique_ptr<C>(Args...)> instead,
1033     // otherwise we'd report an error about a type that the user doesn't expect.
1034     using type = PropagateError(Catch(Catch(R, NoBindingFoundErrorTag, ErrorHandler),
1035                                       NoBindingFoundForAbstractClassErrorTag, ErrorHandler),
1036                                 Op);
1037   };
1038 
1039   // C has an Inject typedef, use it. unique_ptr case.
1040   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused,
1041             typename NakedC, typename AnnotatedSignature, typename... Args>
1042   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<true>, unused,
1043                Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> {
1044     using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature);
1045     using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, RemoveUniquePtr(RemoveAnnotations(AnnotatedCUniquePtr)));
1046     using DecoratedSignatureReturningValue = GetInjectAnnotation(AnnotatedC);
1047     using DecoratedSignature = ConsSignatureWithVector(AnnotatedCUniquePtr,
1048                                                        SignatureArgs(DecoratedSignatureReturningValue));
1049     using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature);
1050     using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature),
1051                                                                       RemoveNonAssisted(DecoratedSignatureArgs));
1052     using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs);
1053 
1054     using F1 = ComponentFunctor(RegisterConstructorAsUniquePtrFactory, DecoratedSignature);
1055     using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements,
1056                                 NormalizeTypeVector(NonAssistedArgs), NormalizedNonConstTypesIn(NonAssistedArgs));
1057 
1058     using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)),
1059                     ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature,
1060                                    ActualSignatureInInjectionTypedef),
1061                     Call(ComposeFunctors(F1, F2), Comp));
1062   };
1063 
1064   // C has an Inject typedef, use it. Value (not unique_ptr) case.
1065   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused,
1066             typename NakedC, typename AnnotatedSignature, typename... Args>
1067   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<true>, unused, Type<NakedC>,
1068                AnnotatedSignature, Args...> {
1069     using AnnotatedC = SignatureType(AnnotatedSignature);
1070     using DecoratedSignature = GetInjectAnnotation(AnnotatedC);
1071     using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature);
1072     using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature),
1073                                                                       RemoveNonAssisted(DecoratedSignatureArgs));
1074     using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs);
1075 
1076     using F1 = ComponentFunctor(RegisterConstructorAsValueFactory, DecoratedSignature);
1077     using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements,
1078                                 NormalizeTypeVector(NonAssistedArgs), NormalizedNonConstTypesIn(NonAssistedArgs));
1079 
1080     using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)),
1081                     ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature,
1082                                    ActualSignatureInInjectionTypedef),
1083                     Call(ComposeFunctors(F1, F2), Comp));
1084   };
1085 };
1086 
1087 struct AutoRegister {
1088   // The types in TargetRequirements will not be auto-registered.
1089   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC>
1090   struct apply;
1091 
1092   // Tries to register C by looking for a typedef called Inject inside C.
1093   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC>
1094   struct apply {
1095     using CHasInjectAnnotation = HasInjectAnnotation(RemoveAnnotations(AnnotatedC));
1096     using Inject = GetInjectAnnotation(AnnotatedC);
1097     using CRequirements = NormalizeTypeVector(SignatureArgs(Inject));
1098     using CNonConstRequirements = NormalizedNonConstTypesIn(SignatureArgs(Inject));
1099     using F = ComposeFunctors(ComponentFunctor(PreProcessRegisterConstructor, Inject),
1100                               ComponentFunctor(PostProcessRegisterConstructor, Inject),
1101                               ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements,
1102                                                CRequirements, CNonConstRequirements));
1103     using type = If(CHasInjectAnnotation, Call(F, Comp), ConstructNoBindingFoundError(AnnotatedC));
1104   };
1105 
1106   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC,
1107             typename... NakedArgs>
1108   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, Type<std::function<NakedC(NakedArgs...)>>> {
1109     using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements,
1110                                            FindInMap(typename Comp::InterfaceBindings, Type<NakedC>),
1111                                            HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>), Type<NakedC>,
1112                                            Type<NakedC(NakedArgs...)>, Id<RemoveAnnotations(Type<NakedArgs>)>...);
1113   };
1114 
1115   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC,
1116             typename... NakedArgs>
1117   struct apply<Comp, TargetRequirements, TargetNonConstRequirements,
1118                Type<std::function<std::unique_ptr<NakedC>(NakedArgs...)>>> {
1119     using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements,
1120                                            FindInMap(typename Comp::InterfaceBindings, Type<NakedC>),
1121                                            HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>),
1122                                            Type<std::unique_ptr<NakedC>>, Type<std::unique_ptr<NakedC>(NakedArgs...)>,
1123                                            Id<RemoveAnnotations(Type<NakedArgs>)>...);
1124   };
1125 
1126   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename Annotation,
1127             typename NakedC, typename... NakedArgs>
1128   struct apply<Comp, TargetRequirements, TargetNonConstRequirements,
1129                Type<fruit::Annotated<Annotation, std::function<NakedC(NakedArgs...)>>>> {
1130     using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements,
1131                                            FindInMap(typename Comp::InterfaceBindings,
1132                                                      Type<fruit::Annotated<Annotation, NakedC>>),
1133                                            HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>), Type<NakedC>,
1134                                            Type<fruit::Annotated<Annotation, NakedC>(NakedArgs...)>,
1135                                            Id<RemoveAnnotations(Type<NakedArgs>)>...);
1136   };
1137 
1138   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename Annotation,
1139             typename NakedC, typename... NakedArgs>
1140   struct apply<Comp, TargetRequirements, TargetNonConstRequirements,
1141                Type<fruit::Annotated<Annotation, std::function<std::unique_ptr<NakedC>(NakedArgs...)>>>> {
1142     using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements,
1143                                            FindInMap(typename Comp::InterfaceBindings,
1144                                                      Type<fruit::Annotated<Annotation, NakedC>>),
1145                                            HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>),
1146                                            Type<std::unique_ptr<NakedC>>,
1147                                            Type<fruit::Annotated<Annotation, std::unique_ptr<NakedC>>(NakedArgs...)>,
1148                                            Id<RemoveAnnotations(Type<NakedArgs>)>...);
1149   };
1150 };
1151 
1152 template <typename AnnotatedT>
1153 struct EnsureProvidedTypeErrorHandler {
1154   template <typename E>
1155   struct apply {
1156     using type = E;
1157   };
1158 
1159   template <typename T>
1160   struct apply<Error<NoBindingFoundErrorTag, T>> {
1161     using type = If(IsSame(Type<T>, AnnotatedT),
1162                     ConstructError(ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag, AnnotatedT),
1163                     ConstructError(NoBindingFoundErrorTag, Type<T>));
1164   };
1165 
1166   template <typename T1, typename T2>
1167   struct apply<Error<NoBindingFoundForAbstractClassErrorTag, T1, T2>> {
1168     using type = If(IsSame(Type<T1>, AnnotatedT),
1169                     ConstructError(ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag, AnnotatedT),
1170                     ConstructError(NoBindingFoundForAbstractClassErrorTag, Type<T1>, Type<T2>));
1171   };
1172 };
1173 
1174 struct EnsureProvidedType {
1175   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedT,
1176             typename NonConstBindingRequired>
1177   struct apply {
1178     using AnnotatedC = NormalizeType(AnnotatedT);
1179     using AnnotatedCImpl = FindInMap(typename Comp::InterfaceBindings, AnnotatedC);
1180     using AutoRegisterResult = AutoRegister(Comp, TargetRequirements, TargetNonConstRequirements, AnnotatedC);
1181     using ErrorHandler = EnsureProvidedTypeErrorHandler<AnnotatedT>;
1182     using type = If(
1183         IsInSet(AnnotatedC, typename Comp::Ps),
1184         If(And(NonConstBindingRequired, Not(IsInSet(AnnotatedC, typename Comp::NonConstRsPs))),
1185            ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, AnnotatedC),
1186            ComponentFunctorIdentity(Comp)),
1187         If(And(IsInSet(AnnotatedC, TargetRequirements),
1188                Or(Not(NonConstBindingRequired), IsInSet(AnnotatedC, TargetNonConstRequirements))),
1189            // The type is already in the target requirements with the desired constness, nothing to do.
1190            ComponentFunctorIdentity(Comp),
1191            If(Not(IsNone(AnnotatedCImpl)),
1192               // Has an interface binding.
1193               Call(ComposeFunctors(ComponentFunctor(ProcessInterfaceBinding, AnnotatedC, AnnotatedCImpl,
1194                                                     NonConstBindingRequired),
1195                                    ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements,
1196                                                     AnnotatedCImpl, NonConstBindingRequired)),
1197                    Comp),
1198               // If we are about to report a NoBindingFound/NoBindingFoundForAbstractClass error for AnnotatedT and the
1199               // target
1200               // component has a Required<const T>, we can report a more specific error (rather than the usual
1201               // "binding not found").
1202               If(And(NonConstBindingRequired, IsInSet(AnnotatedC, TargetRequirements)),
1203                  Catch(Catch(AutoRegisterResult, NoBindingFoundErrorTag, ErrorHandler),
1204                        NoBindingFoundForAbstractClassErrorTag, ErrorHandler),
1205                  AutoRegisterResult))));
1206   };
1207 };
1208 
1209 struct EnsureProvidedTypes {
1210   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename TypesToProvide,
1211             typename NonConstTypesToProvide>
1212   struct apply {
1213     struct Helper {
1214       template <typename CurrentResult, typename T>
1215       struct apply {
1216         using type = Compose2ComponentFunctors(ComponentFunctor(EnsureProvidedType, TargetRequirements,
1217                                                                 TargetNonConstRequirements, T,
1218                                                                 IsInSet(T, NonConstTypesToProvide)),
1219                                                CurrentResult);
1220       };
1221     };
1222 
1223     using type = Call(FoldVector(TypesToProvide, Helper, ComponentFunctorIdentity), Comp);
1224   };
1225 };
1226 
1227 struct ProcessBinding {
1228   template <typename Binding>
1229   struct apply;
1230 
1231   template <typename I, typename C>
1232   struct apply<fruit::impl::Bind<I, C>> {
1233     using type = ComponentFunctor(AddDeferredInterfaceBinding, Type<I>, Type<C>);
1234   };
1235 
1236   template <typename Signature>
1237   struct apply<fruit::impl::RegisterConstructor<Signature>> {
1238     using type = ComponentFunctor(DeferredRegisterConstructor, Type<Signature>);
1239   };
1240 
1241   template <typename AnnotatedC, typename C>
1242   struct apply<fruit::impl::BindInstance<AnnotatedC, C>> {
1243     using type = ComponentFunctor(RegisterInstance, Type<AnnotatedC>, Type<C>, Bool<true>);
1244   };
1245 
1246   template <typename AnnotatedC, typename C>
1247   struct apply<fruit::impl::BindConstInstance<AnnotatedC, C>> {
1248     using type = ComponentFunctor(RegisterInstance, Type<AnnotatedC>, Type<C>, Bool<false>);
1249   };
1250 
1251   template <typename Lambda>
1252   struct apply<fruit::impl::RegisterProvider<Lambda>> {
1253     using type = ComponentFunctor(DeferredRegisterProvider, Type<Lambda>);
1254   };
1255 
1256   template <typename AnnotatedSignature, typename Lambda>
1257   struct apply<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>> {
1258     using type = ComponentFunctor(DeferredRegisterProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>);
1259   };
1260 
1261   template <typename AnnotatedC>
1262   struct apply<fruit::impl::AddInstanceMultibinding<AnnotatedC>> {
1263     using type = ComponentFunctorIdentity;
1264   };
1265 
1266   template <typename AnnotatedC>
1267   struct apply<fruit::impl::AddInstanceVectorMultibindings<AnnotatedC>> {
1268     using type = ComponentFunctorIdentity;
1269   };
1270 
1271   template <typename I, typename C>
1272   struct apply<fruit::impl::AddMultibinding<I, C>> {
1273     using type = ComponentFunctor(AddInterfaceMultibinding, Type<I>, Type<C>);
1274   };
1275 
1276   template <typename Lambda>
1277   struct apply<fruit::impl::AddMultibindingProvider<Lambda>> {
1278     using type = ComponentFunctor(RegisterMultibindingProvider, Type<Lambda>);
1279   };
1280 
1281   template <typename AnnotatedSignature, typename Lambda>
1282   struct apply<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>> {
1283     using type = ComponentFunctor(RegisterMultibindingProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>);
1284   };
1285 
1286   template <typename DecoratedSignature, typename Lambda>
1287   struct apply<fruit::impl::RegisterFactory<DecoratedSignature, Lambda>> {
1288     using type = ComponentFunctor(RegisterFactory, Type<DecoratedSignature>, Type<Lambda>);
1289   };
1290 
1291   template <typename... Params, typename... Args>
1292   struct apply<fruit::impl::InstallComponent<fruit::Component<Params...>(Args...)>> {
1293     using type = ComponentFunctor(InstallComponentHelper, Type<Params>...);
1294   };
1295 
1296   template <typename... ComponentFunctions>
1297   struct apply<fruit::impl::InstallComponentFunctions<ComponentFunctions...>> {
1298     using type = ComponentFunctor(InstallComponentFunctions, Type<ComponentFunctions>...);
1299   };
1300 
1301   template <typename GetReplacedComponent, typename GetReplacementComponent>
1302   struct apply<fruit::impl::ReplaceComponent<GetReplacedComponent, GetReplacementComponent>> {
1303     using type = ComponentFunctorIdentity;
1304   };
1305 };
1306 
1307 } // namespace meta
1308 } // namespace impl
1309 } // namespace fruit
1310 
1311 #endif // FRUIT_COMPONENT_FUNCTORS_DEFN_H
1312