/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FRUIT_INJECTION_ERRORS_H #define FRUIT_INJECTION_ERRORS_H #include #include namespace fruit { namespace impl { template struct AlwaysFalse { static constexpr bool value = false; }; template struct NoBindingFoundError { static_assert(AlwaysFalse::value, "No explicit binding nor C::Inject definition was found for T."); }; template struct NoBindingFoundForAbstractClassError { static_assert(AlwaysFalse::value, "No explicit binding was found for T, and note that C is an abstract class (so Fruit can't auto-inject " "this type, " "even if it has an Inject typedef or an INJECT annotation that will be ignored)."); }; template struct RepeatedTypesError { static_assert(AlwaysFalse::value, "A type was specified more than once. Requirements and provided types should be unique."); }; template struct SelfLoopError { static_assert(AlwaysFalse::value, "Found a loop in the dependencies! The types in TypesInLoop all depend on the next, and the " "last one depends on the first."); }; template struct NonClassTypeError { static_assert(AlwaysFalse::value, "A non-class type T was specified. Use C instead."); }; template struct AnnotatedTypeError { static_assert(AlwaysFalse::value, "An annotated type was specified where a non-annotated type was expected."); }; template struct TypeAlreadyBoundError { static_assert(AlwaysFalse::value, "Trying to bind C but it is already bound."); }; template struct RequiredFactoryWithDifferentSignatureError { static_assert(AlwaysFalse::value, "The required C factory doesn't have the same signature as the Inject annotation in C."); }; template struct AnnotatedSignatureDifferentFromLambdaSignatureError { static_assert(AlwaysFalse::value, "The annotated signature specified is not the same as the lambda's signature (after removing " "annotations)."); }; template struct DuplicateTypesInComponentError { static_assert(AlwaysFalse::value, "The installed component provides some types that are already provided by the current " "component."); }; template struct InjectorWithRequirementsError { static_assert(AlwaysFalse::value, "Injectors can't have requirements. If you want Fruit to try auto-resolving the requirements " "in the injector's scope, cast the component to a component with no requirements before " "constructing the injector with it."); }; template struct InjectTypedefNotASignatureError { static_assert(AlwaysFalse::value, "C::Inject should be a typedef to a signature, e.g. C(int)"); }; template struct InjectTypedefForWrongClassError { static_assert(AlwaysFalse::value, "C::Inject is a signature, but does not return a C. Maybe the class C has no Inject typedef " "and inherited the base class' one? If that's not the case, make sure it returns just C, not " "C* or other types."); }; template struct InjectTypedefWithAnnotationError { static_assert(AlwaysFalse::value, "C::Inject is a signature that returns an annotated type. The annotation must be removed, " "Fruit will deduce the correct annotation based on how the required binding."); }; template struct NotASignatureError { static_assert(AlwaysFalse::value, "CandidateSignature was specified as parameter, but it's not a signature. Signatures are of " "the form MyClass(int, float)."); }; template struct AssistedParamInRegisterConstructorSignatureError { static_assert(AlwaysFalse::value, "CandidateSignature was used as signature for a registerConstructor() (explicit or implicit via the " "INJECT macro / Inject typedef) but it contains an assisted parameter. When using assisted parameters" "You need to inject a factory like std::function(int, float)> instead of " "injecting MyClass directly. If you used an explicit registerConstructor(), you also need to switch " "that to registerFactory()."); }; template struct NotALambdaError { static_assert(AlwaysFalse::value, "CandidateLambda was specified as parameter, but it's not a lambda."); }; template struct ConstructorDoesNotExistError { static_assert(AlwaysFalse::value, "The specified constructor does not exist."); }; template struct NotABaseClassOfError { static_assert(AlwaysFalse::value, "I is not a base class of C."); }; template struct FunctorUsedAsProviderError { static_assert(AlwaysFalse::value, "A stateful lambda or a non-lambda functor was used as provider. Only functions and stateless " "lambdas can be used as providers."); }; template struct ComponentWithRequirementsInInjectorError { static_assert(AlwaysFalse::value, "When using the two-argument constructor of Injector, the component used as second parameter " "must not have requirements (while the normalized component can), but the specified component " "requires ComponentRequirements."); }; template struct UnsatisfiedRequirementsInNormalizedComponentError { static_assert(AlwaysFalse::value, "The requirements in UnsatisfiedRequirements are required by the NormalizedComponent but are " "not provided by the Component (second parameter of the Injector constructor)."); }; template struct TypesInInjectorNotProvidedError { static_assert(AlwaysFalse::value, "The types in TypesNotProvided are declared as provided by the injector, but none of the two " "components passed to the Injector constructor provides them."); }; template struct TypesInInjectorProvidedAsConstOnlyError { static_assert( AlwaysFalse::value, "The types in TypesProvidedAsConstOnly are declared as non-const provided types by the injector, but the " "components passed to the Injector constructor provide them as const only. You should mark them as const in the " "injector (e.g., switching from Injector to Injector) or mark them as non-const in the " "Component/NormalizedComponent (e.g. switching from [Normalized]Component to " "[Normalized]Component)."); }; template struct TypeNotProvidedError { static_assert(AlwaysFalse::value, "Trying to get an instance of T, but it is not provided by this Provider/Injector."); }; template struct TypeProvidedAsConstOnlyError { static_assert( AlwaysFalse::value, "Trying to get an instance of T, but it is only provided as a constant by this Provider/Injector and a non-const " "pointer/reference/Provider was requested. You should either switch to injecting a const value (e.g. switching " "from" " injecting T*, T&, std::unique_ptr or Provider to injecting a T, const T*, const T& or Provider) " "or get the value from an Injector/Provider that provides it as a non-const type (e.g. switching from calling " "get " "on an Injector or on a Provider to calling get on an Injector or a Provider)."); }; template struct NonConstBindingRequiredButConstBindingProvidedError { static_assert( AlwaysFalse::value, "The type T was provided as constant, however one of the constructors/providers/factories in this component " "requires it as a non-constant (or this Component declares it as a non-const provided/required type). " "If you want to only have a const binding for this type, you should change the places that use the type to " "inject " "a constant value (e.g. T, const T*, const T& and Provider are ok while you should avoid injecting T*, " "T&," " std::unique_ptr and Provider) and if the type is in Component<...> make sure that it's marked as const " "there" " (e.g. Component and Component> are ok while Component and Component> " "are " "not. " "On the other hand, if you want to have a non-const binding for this type, you should switch to a non-const " "bindInstance (if you're binding an instance) or changing any installed component functions to declare the type " "as " "non-const, e.g. Component or Component> instead of Component and " "Component>."); }; template struct NoConstructorMatchingInjectSignatureError { static_assert(AlwaysFalse::value, "C contains an Inject typedef but it's not constructible with the specified types"); }; template struct FunctorSignatureDoesNotMatchError { static_assert(AlwaysFalse::value, "Unexpected functor signature (it should be the same as ExpectedSignature minus any Assisted " "types)."); }; template struct FactoryReturningPointerError { static_assert(AlwaysFalse::value, "The specified factory returns a pointer. This is not supported; return a value or an " "std::unique_ptr instead."); }; template struct LambdaWithCapturesError { // It's not guaranteed by the standard, but it's reasonable to expect lambdas with no captures // to be empty. This is always the case in GCC and Clang, but is not guaranteed to work in all // conforming C++ compilers. If this error happens for a lambda with no captures, please file a // bug at https://github.com/google/fruit/issues and indicate the compiler (with version) that // you're using. static_assert(AlwaysFalse::value, "Only lambdas with no captures are supported."); }; template struct NonTriviallyCopyableLambdaError { // It's not guaranteed by the standard, but it's reasonable to expect lambdas with no captures // to be trivially copyable. This is always the case in GCC and Clang, but is not guaranteed to // work in all conforming C++ compilers. If this error happens for a lambda with no captures, // please file a bug at https://github.com/google/fruit/issues and indicate the compiler (with // version) that you're using. static_assert(AlwaysFalse::value, "Only trivially copyable lambdas are supported. Make sure that your lambda has no captures."); }; template struct CannotConstructAbstractClassError { static_assert(AlwaysFalse::value, "The specified class can't be constructed because it's an abstract class."); }; template struct InterfaceBindingToSelfError { static_assert(AlwaysFalse::value, "The type C was bound to itself. If this was intentional, to \"tell Fruit to inject the type" " C\", this binding is unnecessary, just remove it. bind() is to tell Fruit about" " base-derived class relationships."); }; template struct TypeMismatchInBindInstanceError { static_assert(AlwaysFalse::value, "A type parameter was specified in bindInstance() but it doesn't match the value type" " (even after removing the fruit::Annotation<>, if any). Please change the type parameter" " to be the same as the type of the value (or a subclass)."); }; template struct RequiredTypesInComponentArgumentsError { static_assert(AlwaysFalse::value, "A Required<...> type was passed as a non-first template parameter to fruit::Component or " "fruit::NormalizedComponent. " "All required types (if any) should be passed together as a single Required<> type passed as the first " "type argument of fruit::Component (and fruit::NormalizedComponent). For example, write " "fruit::Component, Baz> instead of " "fruit::Component, fruit::Required, Baz>."); }; template struct NonInjectableTypeError { static_assert( AlwaysFalse::value, "The type T is not injectable. Injectable types are of the form X, X*, X&, const X, const X*, const X&, " "std::shared_ptr, or Provider where X is a fundamental type (excluding void), a class, a struct or " "an enum."); }; template struct ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError { static_assert( AlwaysFalse::value, "The type T was declared as a const Required type in the returned Component, however a non-const binding is " "required. You should either change all the usages of this type so that they no longer require a non-const " "binding " "(i.e., you shouldn't inject T*, T& or std::shared_ptr) or you should remove the 'const' in the type of the " "returned Component, e.g. changing fruit::Component, ...> to " "fruit::Component, ...>."); }; template struct ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError { static_assert( AlwaysFalse::value, "registerProvider() was called with a lambda that returns a pointer to T, but T is an abstract class with no " "virtual destructor so when the injector is deleted Fruit will be unable to call the right destructor (the one " "of " "the concrete class that was then casted to T). You must either add a virtual destructor to T or change the " "registerProvider() call to return a pointer to the concrete class (and then add a bind() so that T is " "bound)."); }; template struct MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError { static_assert( AlwaysFalse::value, "registerMultibindingProvider() was called with a lambda that returns a pointer to T, but T is an abstract class " "with no virtual destructor so when the injector is deleted Fruit will be unable to call the right destructor " "(the " "one of the concrete class that was then casted to T). You must add a virtual destructor to T or replace the " "registerMultibindingProvider() with a registerProvider() for the concrete class and an addMultibinding() for T. " "Note that with the latter, if you end up with multiple addMultibinding() calls for the same concrete class, " "there will be only one instance of the concrete class in the injector, not one per addMultibdinding() call; if " "you want separate instances you might want to use annotated injection for the concrete class (so that there's " "one " "instance per annotation)."); }; template struct RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError { static_assert(AlwaysFalse::value, "registerFactory() was called with a lambda that returns a std::unique_ptr, but T is an abstract " "class with no " "virtual destructor so when the returned std::unique_ptr object is deleted the wrong destructor " "will be called " "(T's destructor instead of the one of the concrete class that was then casted to T). You must add a " "virtual destructor to T."); }; template struct FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError { static_assert( AlwaysFalse::value, "Fruit was trying to bind BaseFactory to DerivedFactory but the return type of BaseFactory is a std::unique_ptr " "of " "a class with no virtual destructor, so when the std::unique_ptr object is destroyed the wrong destructor would " "be " "called (the one in the base class instead of the derived class). To avoid this, you must add a virtual " "destructor to the base class."); }; template struct IncorrectArgTypePassedToInstallComponentFuntionsError { static_assert( AlwaysFalse::value, "All arguments passed to installComponentFunctions() must be fruit::ComponentFunction<...> objects but an " "argument with type Arg was passed instead."); }; struct LambdaWithCapturesErrorTag { template using apply = LambdaWithCapturesError; }; struct NonTriviallyCopyableLambdaErrorTag { template using apply = NonTriviallyCopyableLambdaError; }; struct FactoryReturningPointerErrorTag { template using apply = FactoryReturningPointerError; }; struct NoBindingFoundErrorTag { template using apply = NoBindingFoundError; }; struct RepeatedTypesErrorTag { template using apply = RepeatedTypesError; }; struct SelfLoopErrorTag { template using apply = SelfLoopError; }; struct NonClassTypeErrorTag { template using apply = NonClassTypeError; }; struct AnnotatedTypeErrorTag { template using apply = AnnotatedTypeError; }; struct TypeAlreadyBoundErrorTag { template using apply = TypeAlreadyBoundError; }; struct RequiredFactoryWithDifferentSignatureErrorTag { template using apply = RequiredFactoryWithDifferentSignatureError; }; struct AnnotatedSignatureDifferentFromLambdaSignatureErrorTag { template using apply = AnnotatedSignatureDifferentFromLambdaSignatureError; }; struct DuplicateTypesInComponentErrorTag { template using apply = DuplicateTypesInComponentError; }; struct InjectorWithRequirementsErrorTag { template using apply = InjectorWithRequirementsError; }; struct ComponentWithRequirementsInInjectorErrorTag { template using apply = ComponentWithRequirementsInInjectorError; }; struct InjectTypedefNotASignatureErrorTag { template using apply = InjectTypedefNotASignatureError; }; struct InjectTypedefForWrongClassErrorTag { template using apply = InjectTypedefForWrongClassError; }; struct InjectTypedefWithAnnotationErrorTag { template using apply = InjectTypedefWithAnnotationError; }; struct UnsatisfiedRequirementsInNormalizedComponentErrorTag { template using apply = UnsatisfiedRequirementsInNormalizedComponentError; }; struct TypesInInjectorNotProvidedErrorTag { template using apply = TypesInInjectorNotProvidedError; }; struct TypesInInjectorProvidedAsConstOnlyErrorTag { template using apply = TypesInInjectorProvidedAsConstOnlyError; }; struct FunctorUsedAsProviderErrorTag { template using apply = FunctorUsedAsProviderError; }; struct ConstructorDoesNotExistErrorTag { template using apply = ConstructorDoesNotExistError; }; struct NotABaseClassOfErrorTag { template using apply = NotABaseClassOfError; }; struct NotASignatureErrorTag { template using apply = NotASignatureError; }; struct AssistedParamInRegisterConstructorSignatureErrorTag { template using apply = AssistedParamInRegisterConstructorSignatureError; }; struct NotALambdaErrorTag { template using apply = NotALambdaError; }; struct TypeNotProvidedErrorTag { template using apply = TypeNotProvidedError; }; struct TypeProvidedAsConstOnlyErrorTag { template using apply = TypeProvidedAsConstOnlyError; }; struct NonConstBindingRequiredButConstBindingProvidedErrorTag { template using apply = NonConstBindingRequiredButConstBindingProvidedError; }; struct NoConstructorMatchingInjectSignatureErrorTag { template using apply = NoConstructorMatchingInjectSignatureError; }; struct FunctorSignatureDoesNotMatchErrorTag { template using apply = FunctorSignatureDoesNotMatchError; }; struct CannotConstructAbstractClassErrorTag { template using apply = CannotConstructAbstractClassError; }; struct NoBindingFoundForAbstractClassErrorTag { template using apply = NoBindingFoundForAbstractClassError; }; struct InterfaceBindingToSelfErrorTag { template using apply = InterfaceBindingToSelfError; }; struct TypeMismatchInBindInstanceErrorTag { template using apply = TypeMismatchInBindInstanceError; }; struct RequiredTypesInComponentArgumentsErrorTag { template using apply = RequiredTypesInComponentArgumentsError; }; struct NonInjectableTypeErrorTag { template using apply = NonInjectableTypeError; }; struct ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag { template using apply = ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError; }; struct ProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag { template using apply = ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError; }; struct MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag { template using apply = MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError; }; struct RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorErrorTag { template using apply = RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError; }; struct FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorErrorTag { template using apply = FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError; }; struct IncorrectArgTypePassedToInstallComponentFuntionsErrorTag { template using apply = IncorrectArgTypePassedToInstallComponentFuntionsError; }; } // namespace impl } // namespace fruit #endif // FRUIT_INJECTION_ERRORS_H