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