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_INJECTION_ERRORS_H
18 #define FRUIT_INJECTION_ERRORS_H
19 
20 #include <fruit/impl/fruit_assert.h>
21 #include <fruit/impl/meta/set.h>
22 
23 namespace fruit {
24 namespace impl {
25 
26 template <typename... Ts>
27 struct AlwaysFalse {
28   static constexpr bool value = false;
29 };
30 
31 template <typename T>
32 struct NoBindingFoundError {
33   static_assert(AlwaysFalse<T>::value, "No explicit binding nor C::Inject definition was found for T.");
34 };
35 
36 template <typename T, typename C>
37 struct NoBindingFoundForAbstractClassError {
38   static_assert(AlwaysFalse<T>::value,
39                 "No explicit binding was found for T, and note that C is an abstract class (so Fruit can't auto-inject "
40                 "this type, "
41                 "even if it has an Inject typedef or an INJECT annotation that will be ignored).");
42 };
43 
44 template <typename... Ts>
45 struct RepeatedTypesError {
46   static_assert(AlwaysFalse<Ts...>::value,
47                 "A type was specified more than once. Requirements and provided types should be unique.");
48 };
49 
50 template <typename... TypesInLoop>
51 struct SelfLoopError {
52   static_assert(AlwaysFalse<TypesInLoop...>::value,
53                 "Found a loop in the dependencies! The types in TypesInLoop all depend on the next, and the "
54                 "last one depends on the first.");
55 };
56 
57 template <typename T, typename C>
58 struct NonClassTypeError {
59   static_assert(AlwaysFalse<T>::value, "A non-class type T was specified. Use C instead.");
60 };
61 
62 template <typename AnnotatedT, typename T>
63 struct AnnotatedTypeError {
64   static_assert(AlwaysFalse<T>::value, "An annotated type was specified where a non-annotated type was expected.");
65 };
66 
67 template <typename C>
68 struct TypeAlreadyBoundError {
69   static_assert(AlwaysFalse<C>::value, "Trying to bind C but it is already bound.");
70 };
71 
72 template <typename RequiredSignature, typename SignatureInInjectTypedef>
73 struct RequiredFactoryWithDifferentSignatureError {
74   static_assert(AlwaysFalse<RequiredSignature>::value,
75                 "The required C factory doesn't have the same signature as the Inject annotation in C.");
76 };
77 
78 template <typename Signature, typename SignatureInLambda>
79 struct AnnotatedSignatureDifferentFromLambdaSignatureError {
80   static_assert(AlwaysFalse<Signature>::value,
81                 "The annotated signature specified is not the same as the lambda's signature (after removing "
82                 "annotations).");
83 };
84 
85 template <typename... DuplicatedTypes>
86 struct DuplicateTypesInComponentError {
87   static_assert(AlwaysFalse<DuplicatedTypes...>::value,
88                 "The installed component provides some types that are already provided by the current "
89                 "component.");
90 };
91 
92 template <typename... Requirements>
93 struct InjectorWithRequirementsError {
94   static_assert(AlwaysFalse<Requirements...>::value,
95                 "Injectors can't have requirements. If you want Fruit to try auto-resolving the requirements "
96                 "in the injector's scope, cast the component to a component with no requirements before "
97                 "constructing the injector with it.");
98 };
99 
100 template <typename C, typename CandidateSignature>
101 struct InjectTypedefNotASignatureError {
102   static_assert(AlwaysFalse<C>::value, "C::Inject should be a typedef to a signature, e.g. C(int)");
103 };
104 
105 template <typename C, typename SignatureReturnType>
106 struct InjectTypedefForWrongClassError {
107   static_assert(AlwaysFalse<C>::value,
108                 "C::Inject is a signature, but does not return a C. Maybe the class C has no Inject typedef "
109                 "and inherited the base class' one? If that's not the case, make sure it returns just C, not "
110                 "C* or other types.");
111 };
112 
113 template <typename C>
114 struct InjectTypedefWithAnnotationError {
115   static_assert(AlwaysFalse<C>::value,
116                 "C::Inject is a signature that returns an annotated type. The annotation must be removed, "
117                 "Fruit will deduce the correct annotation based on how the required binding.");
118 };
119 
120 template <typename CandidateSignature>
121 struct NotASignatureError {
122   static_assert(AlwaysFalse<CandidateSignature>::value,
123                 "CandidateSignature was specified as parameter, but it's not a signature. Signatures are of "
124                 "the form MyClass(int, float).");
125 };
126 
127 template <typename CandidateSignature>
128 struct AssistedParamInRegisterConstructorSignatureError {
129   static_assert(AlwaysFalse<CandidateSignature>::value,
130                 "CandidateSignature was used as signature for a registerConstructor() (explicit or implicit via the "
131                 "INJECT macro / Inject typedef) but it contains an assisted parameter. When using assisted parameters"
132                 "You need to inject a factory like std::function<std::unique_ptr<MyClass>(int, float)> instead of "
133                 "injecting MyClass directly. If you used an explicit registerConstructor(), you also need to switch "
134                 "that to registerFactory().");
135 };
136 
137 template <typename CandidateLambda>
138 struct NotALambdaError {
139   static_assert(AlwaysFalse<CandidateLambda>::value,
140                 "CandidateLambda was specified as parameter, but it's not a lambda.");
141 };
142 
143 template <typename Signature>
144 struct ConstructorDoesNotExistError {
145   static_assert(AlwaysFalse<Signature>::value, "The specified constructor does not exist.");
146 };
147 
148 template <typename I, typename C>
149 struct NotABaseClassOfError {
150   static_assert(AlwaysFalse<I>::value, "I is not a base class of C.");
151 };
152 
153 template <typename ProviderType>
154 struct FunctorUsedAsProviderError {
155   static_assert(AlwaysFalse<ProviderType>::value,
156                 "A stateful lambda or a non-lambda functor was used as provider. Only functions and stateless "
157                 "lambdas can be used as providers.");
158 };
159 
160 template <typename... ComponentRequirements>
161 struct ComponentWithRequirementsInInjectorError {
162   static_assert(AlwaysFalse<ComponentRequirements...>::value,
163                 "When using the two-argument constructor of Injector, the component used as second parameter "
164                 "must not have requirements (while the normalized component can), but the specified component "
165                 "requires ComponentRequirements.");
166 };
167 
168 template <typename... UnsatisfiedRequirements>
169 struct UnsatisfiedRequirementsInNormalizedComponentError {
170   static_assert(AlwaysFalse<UnsatisfiedRequirements...>::value,
171                 "The requirements in UnsatisfiedRequirements are required by the NormalizedComponent but are "
172                 "not provided by the Component (second parameter of the Injector constructor).");
173 };
174 
175 template <typename... TypesNotProvided>
176 struct TypesInInjectorNotProvidedError {
177   static_assert(AlwaysFalse<TypesNotProvided...>::value,
178                 "The types in TypesNotProvided are declared as provided by the injector, but none of the two "
179                 "components passed to the Injector constructor provides them.");
180 };
181 
182 template <typename... TypesProvidedAsConstOnly>
183 struct TypesInInjectorProvidedAsConstOnlyError {
184   static_assert(
185       AlwaysFalse<TypesProvidedAsConstOnly...>::value,
186       "The types in TypesProvidedAsConstOnly are declared as non-const provided types by the injector, but the "
187       "components passed to the Injector constructor provide them as const only. You should mark them as const in the "
188       "injector (e.g., switching from Injector<T> to Injector<const T>) or mark them as non-const in the "
189       "Component/NormalizedComponent (e.g. switching from [Normalized]Component<const T> to "
190       "[Normalized]Component<T>).");
191 };
192 
193 template <typename T>
194 struct TypeNotProvidedError {
195   static_assert(AlwaysFalse<T>::value,
196                 "Trying to get an instance of T, but it is not provided by this Provider/Injector.");
197 };
198 
199 template <typename T>
200 struct TypeProvidedAsConstOnlyError {
201   static_assert(
202       AlwaysFalse<T>::value,
203       "Trying to get an instance of T, but it is only provided as a constant by this Provider/Injector and a non-const "
204       "pointer/reference/Provider was requested. You should either switch to injecting a const value (e.g. switching "
205       "from"
206       " injecting T*, T&, std::unique_ptr<T> or Provider<T> to injecting a T, const T*, const T& or Provider<const T>) "
207       "or get the value from an Injector/Provider that provides it as a non-const type (e.g. switching from calling "
208       "get "
209       "on an Injector<const T> or on a Provider<const T> to calling get on an Injector<T> or a Provider<T>).");
210 };
211 
212 template <typename T>
213 struct NonConstBindingRequiredButConstBindingProvidedError {
214   static_assert(
215       AlwaysFalse<T>::value,
216       "The type T was provided as constant, however one of the constructors/providers/factories in this component "
217       "requires it as a non-constant (or this Component declares it as a non-const provided/required type). "
218       "If you want to only have a const binding for this type, you should change the places that use the type to "
219       "inject "
220       "a constant value (e.g. T, const T*, const T& and Provider<const T> are ok while you should avoid injecting T*, "
221       "T&,"
222       " std::unique_ptr<T> and Provider<T>) and if the type is in Component<...> make sure that it's marked as const "
223       "there"
224       " (e.g. Component<const T> and Component<Required<const T>> are ok while Component<T> and Component<Required<T>> "
225       "are "
226       "not. "
227       "On the other hand, if you want to have a non-const binding for this type, you should switch to a non-const "
228       "bindInstance (if you're binding an instance) or changing any installed component functions to declare the type "
229       "as "
230       "non-const, e.g. Component<T> or Component<Required<T>> instead of Component<const T> and "
231       "Component<Required<const T>>.");
232 };
233 
234 template <typename C, typename InjectSignature>
235 struct NoConstructorMatchingInjectSignatureError {
236   static_assert(AlwaysFalse<C>::value,
237                 "C contains an Inject typedef but it's not constructible with the specified types");
238 };
239 
240 template <typename ExpectedSignature, typename FunctorSignature>
241 struct FunctorSignatureDoesNotMatchError {
242   static_assert(AlwaysFalse<ExpectedSignature>::value,
243                 "Unexpected functor signature (it should be the same as ExpectedSignature minus any Assisted "
244                 "types).");
245 };
246 
247 template <typename Signature>
248 struct FactoryReturningPointerError {
249   static_assert(AlwaysFalse<Signature>::value,
250                 "The specified factory returns a pointer. This is not supported; return a value or an "
251                 "std::unique_ptr instead.");
252 };
253 
254 template <typename Lambda>
255 struct LambdaWithCapturesError {
256   // It's not guaranteed by the standard, but it's reasonable to expect lambdas with no captures
257   // to be empty. This is always the case in GCC and Clang, but is not guaranteed to work in all
258   // conforming C++ compilers. If this error happens for a lambda with no captures, please file a
259   // bug at https://github.com/google/fruit/issues and indicate the compiler (with version) that
260   // you're using.
261   static_assert(AlwaysFalse<Lambda>::value, "Only lambdas with no captures are supported.");
262 };
263 
264 template <typename Lambda>
265 struct NonTriviallyCopyableLambdaError {
266   // It's not guaranteed by the standard, but it's reasonable to expect lambdas with no captures
267   // to be trivially copyable. This is always the case in GCC and Clang, but is not guaranteed to
268   // work in all conforming C++ compilers. If this error happens for a lambda with no captures,
269   // please file a bug at https://github.com/google/fruit/issues and indicate the compiler (with
270   // version) that you're using.
271   static_assert(AlwaysFalse<Lambda>::value,
272                 "Only trivially copyable lambdas are supported. Make sure that your lambda has no captures.");
273 };
274 
275 template <typename C>
276 struct CannotConstructAbstractClassError {
277   static_assert(AlwaysFalse<C>::value, "The specified class can't be constructed because it's an abstract class.");
278 };
279 
280 template <typename C>
281 struct InterfaceBindingToSelfError {
282   static_assert(AlwaysFalse<C>::value,
283                 "The type C was bound to itself. If this was intentional, to \"tell Fruit to inject the type"
284                 " C\", this binding is unnecessary, just remove it. bind<I,C>() is to tell Fruit about"
285                 " base-derived class relationships.");
286 };
287 
288 template <typename TypeParameter, typename TypeOfValue>
289 struct TypeMismatchInBindInstanceError {
290   static_assert(AlwaysFalse<TypeParameter>::value,
291                 "A type parameter was specified in bindInstance() but it doesn't match the value type"
292                 " (even after removing the fruit::Annotation<>, if any). Please change the type parameter"
293                 " to be the same as the type of the value (or a subclass).");
294 };
295 
296 template <typename RequiredType>
297 struct RequiredTypesInComponentArgumentsError {
298   static_assert(AlwaysFalse<RequiredType>::value,
299                 "A Required<...> type was passed as a non-first template parameter to fruit::Component or "
300                 "fruit::NormalizedComponent. "
301                 "All required types (if any) should be passed together as a single Required<> type passed as the first "
302                 "type argument of fruit::Component (and fruit::NormalizedComponent). For example, write "
303                 "fruit::Component<fruit::Required<Foo, Bar>, Baz> instead of "
304                 "fruit::Component<fruit::Required<Foo>, fruit::Required<Bar>, Baz>.");
305 };
306 
307 template <typename T>
308 struct NonInjectableTypeError {
309   static_assert(
310       AlwaysFalse<T>::value,
311       "The type T is not injectable. Injectable types are of the form X, X*, X&, const X, const X*, const X&, "
312       "std::shared_ptr<X>, or Provider<X> where X is a fundamental type (excluding void), a class, a struct or "
313       "an enum.");
314 };
315 
316 template <typename T>
317 struct ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError {
318   static_assert(
319       AlwaysFalse<T>::value,
320       "The type T was declared as a const Required type in the returned Component, however a non-const binding is "
321       "required. You should either change all the usages of this type so that they no longer require a non-const "
322       "binding "
323       "(i.e., you shouldn't inject T*, T& or std::shared_ptr<T>) or you should remove the 'const' in the type of the "
324       "returned Component, e.g. changing fruit::Component<fruit::Required<const T, ...>, ...> to "
325       "fruit::Component<fruit::Required<T, ...>, ...>.");
326 };
327 
328 template <typename T>
329 struct ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError {
330   static_assert(
331       AlwaysFalse<T>::value,
332       "registerProvider() was called with a lambda that returns a pointer to T, but T is an abstract class with no "
333       "virtual destructor so when the injector is deleted Fruit will be unable to call the right destructor (the one "
334       "of "
335       "the concrete class that was then casted to T). You must either add a virtual destructor to T or change the "
336       "registerProvider() call to return a pointer to the concrete class (and then add a bind<T, TImpl>() so that T is "
337       "bound).");
338 };
339 
340 template <typename T>
341 struct MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError {
342   static_assert(
343       AlwaysFalse<T>::value,
344       "registerMultibindingProvider() was called with a lambda that returns a pointer to T, but T is an abstract class "
345       "with no virtual destructor so when the injector is deleted Fruit will be unable to call the right destructor "
346       "(the "
347       "one of the concrete class that was then casted to T). You must add a virtual destructor to T or replace the "
348       "registerMultibindingProvider() with a registerProvider() for the concrete class and an addMultibinding() for T. "
349       "Note that with the latter, if you end up with multiple addMultibinding() calls for the same concrete class, "
350       "there will be only one instance of the concrete class in the injector, not one per addMultibdinding() call; if "
351       "you want separate instances you might want to use annotated injection for the concrete class (so that there's "
352       "one "
353       "instance per annotation).");
354 };
355 
356 template <typename T>
357 struct RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError {
358   static_assert(AlwaysFalse<T>::value,
359                 "registerFactory() was called with a lambda that returns a std::unique_ptr<T>, but T is an abstract "
360                 "class with no "
361                 "virtual destructor so when the returned std::unique_ptr<T> object is deleted the wrong destructor "
362                 "will be called "
363                 "(T's destructor instead of the one of the concrete class that was then casted to T). You must add a "
364                 "virtual destructor to T.");
365 };
366 
367 template <typename BaseFactory, typename DerivedFactory>
368 struct FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError {
369   static_assert(
370       AlwaysFalse<BaseFactory>::value,
371       "Fruit was trying to bind BaseFactory to DerivedFactory but the return type of BaseFactory is a std::unique_ptr "
372       "of "
373       "a class with no virtual destructor, so when the std::unique_ptr object is destroyed the wrong destructor would "
374       "be "
375       "called (the one in the base class instead of the derived class). To avoid this, you must add a virtual "
376       "destructor to the base class.");
377 };
378 
379 template <typename Arg>
380 struct IncorrectArgTypePassedToInstallComponentFuntionsError {
381     static_assert(
382         AlwaysFalse<Arg>::value,
383         "All arguments passed to installComponentFunctions() must be fruit::ComponentFunction<...> objects but an "
384         "argument with type Arg was passed instead.");
385 };
386 
387 struct LambdaWithCapturesErrorTag {
388   template <typename Lambda>
389   using apply = LambdaWithCapturesError<Lambda>;
390 };
391 
392 struct NonTriviallyCopyableLambdaErrorTag {
393   template <typename Lambda>
394   using apply = NonTriviallyCopyableLambdaError<Lambda>;
395 };
396 
397 struct FactoryReturningPointerErrorTag {
398   template <typename Signature>
399   using apply = FactoryReturningPointerError<Signature>;
400 };
401 
402 struct NoBindingFoundErrorTag {
403   template <typename T>
404   using apply = NoBindingFoundError<T>;
405 };
406 
407 struct RepeatedTypesErrorTag {
408   template <typename... Ts>
409   using apply = RepeatedTypesError<Ts...>;
410 };
411 
412 struct SelfLoopErrorTag {
413   template <typename... TypesInLoop>
414   using apply = SelfLoopError<TypesInLoop...>;
415 };
416 
417 struct NonClassTypeErrorTag {
418   template <typename T, typename C>
419   using apply = NonClassTypeError<T, C>;
420 };
421 
422 struct AnnotatedTypeErrorTag {
423   template <typename T, typename C>
424   using apply = AnnotatedTypeError<T, C>;
425 };
426 
427 struct TypeAlreadyBoundErrorTag {
428   template <typename C>
429   using apply = TypeAlreadyBoundError<C>;
430 };
431 
432 struct RequiredFactoryWithDifferentSignatureErrorTag {
433   template <typename RequiredSignature, typename SignatureInInjectTypedef>
434   using apply = RequiredFactoryWithDifferentSignatureError<RequiredSignature, SignatureInInjectTypedef>;
435 };
436 
437 struct AnnotatedSignatureDifferentFromLambdaSignatureErrorTag {
438   template <typename Signature, typename SignatureInLambda>
439   using apply = AnnotatedSignatureDifferentFromLambdaSignatureError<Signature, SignatureInLambda>;
440 };
441 
442 struct DuplicateTypesInComponentErrorTag {
443   template <typename... DuplicatedTypes>
444   using apply = DuplicateTypesInComponentError<DuplicatedTypes...>;
445 };
446 
447 struct InjectorWithRequirementsErrorTag {
448   template <typename... Requirements>
449   using apply = InjectorWithRequirementsError<Requirements...>;
450 };
451 
452 struct ComponentWithRequirementsInInjectorErrorTag {
453   template <typename... ComponentRequirements>
454   using apply = ComponentWithRequirementsInInjectorError<ComponentRequirements...>;
455 };
456 
457 struct InjectTypedefNotASignatureErrorTag {
458   template <typename C, typename TypeInInjectTypedef>
459   using apply = InjectTypedefNotASignatureError<C, TypeInInjectTypedef>;
460 };
461 
462 struct InjectTypedefForWrongClassErrorTag {
463   template <typename C, typename ReturnTypeOfInjectTypedef>
464   using apply = InjectTypedefForWrongClassError<C, ReturnTypeOfInjectTypedef>;
465 };
466 
467 struct InjectTypedefWithAnnotationErrorTag {
468   template <typename C>
469   using apply = InjectTypedefWithAnnotationError<C>;
470 };
471 
472 struct UnsatisfiedRequirementsInNormalizedComponentErrorTag {
473   template <typename... UnsatisfiedRequirements>
474   using apply = UnsatisfiedRequirementsInNormalizedComponentError<UnsatisfiedRequirements...>;
475 };
476 
477 struct TypesInInjectorNotProvidedErrorTag {
478   template <typename... TypesNotProvided>
479   using apply = TypesInInjectorNotProvidedError<TypesNotProvided...>;
480 };
481 
482 struct TypesInInjectorProvidedAsConstOnlyErrorTag {
483   template <typename... TypesProvidedAsConstOnly>
484   using apply = TypesInInjectorProvidedAsConstOnlyError<TypesProvidedAsConstOnly...>;
485 };
486 
487 struct FunctorUsedAsProviderErrorTag {
488   template <typename ProviderType>
489   using apply = FunctorUsedAsProviderError<ProviderType>;
490 };
491 
492 struct ConstructorDoesNotExistErrorTag {
493   template <typename Signature>
494   using apply = ConstructorDoesNotExistError<Signature>;
495 };
496 
497 struct NotABaseClassOfErrorTag {
498   template <typename I, typename C>
499   using apply = NotABaseClassOfError<I, C>;
500 };
501 
502 struct NotASignatureErrorTag {
503   template <typename CandidateSignature>
504   using apply = NotASignatureError<CandidateSignature>;
505 };
506 
507 struct AssistedParamInRegisterConstructorSignatureErrorTag {
508   template <typename CandidateSignature>
509   using apply = AssistedParamInRegisterConstructorSignatureError<CandidateSignature>;
510 };
511 
512 struct NotALambdaErrorTag {
513   template <typename CandidateLambda>
514   using apply = NotALambdaError<CandidateLambda>;
515 };
516 
517 struct TypeNotProvidedErrorTag {
518   template <typename T>
519   using apply = TypeNotProvidedError<T>;
520 };
521 
522 struct TypeProvidedAsConstOnlyErrorTag {
523   template <typename T>
524   using apply = TypeProvidedAsConstOnlyError<T>;
525 };
526 
527 struct NonConstBindingRequiredButConstBindingProvidedErrorTag {
528   template <typename T>
529   using apply = NonConstBindingRequiredButConstBindingProvidedError<T>;
530 };
531 
532 struct NoConstructorMatchingInjectSignatureErrorTag {
533   template <typename C, typename InjectSignature>
534   using apply = NoConstructorMatchingInjectSignatureError<C, InjectSignature>;
535 };
536 
537 struct FunctorSignatureDoesNotMatchErrorTag {
538   template <typename ExpectedSignature, typename FunctorSignature>
539   using apply = FunctorSignatureDoesNotMatchError<ExpectedSignature, FunctorSignature>;
540 };
541 
542 struct CannotConstructAbstractClassErrorTag {
543   template <typename C>
544   using apply = CannotConstructAbstractClassError<C>;
545 };
546 
547 struct NoBindingFoundForAbstractClassErrorTag {
548   template <typename T, typename C>
549   using apply = NoBindingFoundForAbstractClassError<T, C>;
550 };
551 
552 struct InterfaceBindingToSelfErrorTag {
553   template <typename C>
554   using apply = InterfaceBindingToSelfError<C>;
555 };
556 
557 struct TypeMismatchInBindInstanceErrorTag {
558   template <typename TypeParameter, typename TypeOfValue>
559   using apply = TypeMismatchInBindInstanceError<TypeParameter, TypeOfValue>;
560 };
561 
562 struct RequiredTypesInComponentArgumentsErrorTag {
563   template <typename RequiredType>
564   using apply = RequiredTypesInComponentArgumentsError<RequiredType>;
565 };
566 
567 struct NonInjectableTypeErrorTag {
568   template <typename T>
569   using apply = NonInjectableTypeError<T>;
570 };
571 
572 struct ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag {
573   template <typename T>
574   using apply = ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<T>;
575 };
576 
577 struct ProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag {
578   template <typename T>
579   using apply = ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError<T>;
580 };
581 
582 struct MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag {
583   template <typename T>
584   using apply = MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError<T>;
585 };
586 
587 struct RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorErrorTag {
588   template <typename T>
589   using apply = RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError<T>;
590 };
591 
592 struct FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorErrorTag {
593   template <typename BaseFactory, typename DerivedFactory>
594   using apply = FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError<BaseFactory, DerivedFactory>;
595 };
596 
597 struct IncorrectArgTypePassedToInstallComponentFuntionsErrorTag {
598   template <typename Arg>
599   using apply = IncorrectArgTypePassedToInstallComponentFuntionsError<Arg>;
600 };
601 
602 } // namespace impl
603 } // namespace fruit
604 
605 #endif // FRUIT_INJECTION_ERRORS_H
606