@@ -7601,67 +7601,147 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
7601
7601
}
7602
7602
7603
7603
// We have a type constructor.
7604
- auto metaTy = cs.getType (fn)->castTo <AnyMetatypeType>();
7605
- auto ty = metaTy->getInstanceType ();
7606
-
7607
- if (!cs.isTypeReference (fn)) {
7608
- bool isExistentialType = false ;
7609
- // If this is an attempt to initialize existential type.
7610
- if (auto metaType = cs.getType (fn)->getAs <MetatypeType>()) {
7611
- auto instanceType = metaType->getInstanceType ();
7612
- isExistentialType = instanceType->isExistentialType ();
7613
- }
7604
+ if (auto metaTy = cs.getType (fn)->getAs <AnyMetatypeType>()) {
7605
+ auto ty = metaTy->getInstanceType ();
7606
+
7607
+ if (!cs.isTypeReference (fn)) {
7608
+ bool isExistentialType = false ;
7609
+ // If this is an attempt to initialize existential type.
7610
+ if (auto metaType = cs.getType (fn)->getAs <MetatypeType>()) {
7611
+ auto instanceType = metaType->getInstanceType ();
7612
+ isExistentialType = instanceType->isExistentialType ();
7613
+ }
7614
+
7615
+ if (!isExistentialType) {
7616
+ // If the metatype value isn't a type expression,
7617
+ // the user should reference '.init' explicitly, for clarity.
7618
+ cs.TC
7619
+ .diagnose (apply->getArg ()->getStartLoc (),
7620
+ diag::missing_init_on_metatype_initialization)
7621
+ .fixItInsert (apply->getArg ()->getStartLoc (), " .init" );
7622
+ }
7623
+ }
7624
+
7625
+ // If we're "constructing" a tuple type, it's simply a conversion.
7626
+ if (auto tupleTy = ty->getAs <TupleType>()) {
7627
+ // FIXME: Need an AST to represent this properly.
7628
+ return coerceToType (apply->getArg (), tupleTy, locator);
7629
+ }
7630
+
7631
+ // We're constructing a value of nominal type. Look for the constructor or
7632
+ // enum element to use.
7633
+ auto ctorLocator = cs.getConstraintLocator (
7634
+ locator.withPathElement (ConstraintLocator::ApplyFunction)
7635
+ .withPathElement (ConstraintLocator::ConstructorMember));
7636
+ auto selected = getOverloadChoiceIfAvailable (ctorLocator);
7637
+ if (!selected) {
7638
+ assert (ty->hasError () || ty->hasUnresolvedType ());
7639
+ cs.setType (apply, ty);
7640
+ return apply;
7641
+ }
7642
+
7643
+ assert (ty->getNominalOrBoundGenericNominal () || ty->is <DynamicSelfType>() ||
7644
+ ty->isExistentialType () || ty->is <ArchetypeType>());
7645
+
7646
+ // We have the constructor.
7647
+ auto choice = selected->choice ;
7648
+
7649
+ // Consider the constructor decl reference expr 'implicit', but the
7650
+ // constructor call expr itself has the apply's 'implicitness'.
7651
+ bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7652
+ Expr *declRef = buildMemberRef (fn, selected->openedFullType ,
7653
+ /* dotLoc=*/ SourceLoc (), choice,
7654
+ DeclNameLoc (fn->getEndLoc ()),
7655
+ selected->openedType , locator, ctorLocator,
7656
+ /* Implicit=*/ true , choice.getFunctionRefKind (),
7657
+ AccessSemantics::Ordinary, isDynamic);
7658
+ if (!declRef)
7659
+ return nullptr ;
7660
+ declRef->setImplicit (apply->isImplicit ());
7661
+ apply->setFn (declRef);
7614
7662
7615
- if (!isExistentialType) {
7616
- // If the metatype value isn't a type expression,
7617
- // the user should reference '.init' explicitly, for clarity.
7618
- cs.TC
7619
- .diagnose (apply->getArg ()->getStartLoc (),
7620
- diag::missing_init_on_metatype_initialization)
7621
- .fixItInsert (apply->getArg ()->getStartLoc (), " .init" );
7622
- }
7663
+ // Tail-recur to actually call the constructor.
7664
+ return finishApply (apply, openedType, locator);
7623
7665
}
7624
7666
7625
- // If we're "constructing" a tuple type, it's simply a conversion.
7626
- if (auto tupleTy = ty->getAs <TupleType>()) {
7627
- // FIXME: Need an AST to represent this properly.
7628
- return coerceToType (apply->getArg (), tupleTy, locator);
7629
- }
7667
+ // Handle @dynamicCallable applications.
7668
+ // At this point, all other AppyExpr cases have been handled.
7669
+ auto isDynamicCallable = [&](Expr *base) {
7670
+ auto type = cs.getType (base);
7671
+ return type && cs.DynamicCallableCache .count (type->getCanonicalType ());
7672
+ };
7673
+ assert (isDynamicCallable (fn) && " Expected a valid @dynamicCallable type" );
7630
7674
7631
- // We're constructing a value of nominal type. Look for the constructor or
7632
- // enum element to use.
7633
- auto ctorLocator = cs.getConstraintLocator (
7634
- locator.withPathElement (ConstraintLocator::ApplyFunction)
7635
- .withPathElement (ConstraintLocator::ConstructorMember));
7636
- auto selected = getOverloadChoiceIfAvailable (ctorLocator);
7637
- if (!selected) {
7638
- assert (ty->hasError () || ty->hasUnresolvedType ());
7639
- cs.setType (apply, ty);
7640
- return apply;
7641
- }
7675
+ auto &ctx = tc.Context ;
7676
+ auto methods = cs.DynamicCallableCache [cs.getType (fn)->getCanonicalType ()];
7677
+ assert (methods.isValid () && " Expected a valid @dynamicCallable type" );
7642
7678
7643
- assert (ty->getNominalOrBoundGenericNominal () || ty->is <DynamicSelfType>() ||
7644
- ty->isExistentialType () || ty->is <ArchetypeType>());
7679
+ TupleExpr *arg = dyn_cast<TupleExpr>(apply->getArg ());
7680
+ if (auto parenExpr = dyn_cast<ParenExpr>(apply->getArg ())) {
7681
+ arg = TupleExpr::createImplicit (ctx, parenExpr->getSubExpr (), {});
7682
+ }
7645
7683
7646
- // We have the constructor.
7647
- auto choice = selected->choice ;
7648
-
7649
- // Consider the constructor decl reference expr 'implicit', but the
7650
- // constructor call expr itself has the apply's 'implicitness'.
7651
- bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7652
- Expr *declRef = buildMemberRef (fn, selected->openedFullType ,
7653
- /* dotLoc=*/ SourceLoc (), choice,
7654
- DeclNameLoc (fn->getEndLoc ()),
7655
- selected->openedType , locator, ctorLocator,
7656
- /* Implicit=*/ true , choice.getFunctionRefKind (),
7657
- AccessSemantics::Ordinary, isDynamic);
7658
- if (!declRef)
7659
- return nullptr ;
7660
- declRef->setImplicit (apply->isImplicit ());
7661
- apply->setFn (declRef);
7684
+ // Determine whether to call the positional arguments method or the
7685
+ // keyword arguments method.
7686
+ bool useKwargsMethod = methods.argumentsMethod == nullptr ;
7687
+ if (!useKwargsMethod) {
7688
+ for (auto name : arg->getElementNames ()) {
7689
+ if (!name.empty ()) {
7690
+ useKwargsMethod = true ;
7691
+ break ;
7692
+ }
7693
+ }
7694
+ }
7662
7695
7663
- // Tail-recur to actually call the constructor.
7664
- return finishApply (apply, openedType, locator);
7696
+ auto method = useKwargsMethod
7697
+ ? methods.keywordArgumentsMethod
7698
+ : methods.argumentsMethod ;
7699
+ assert (method && " Dynamic call method should exist" );
7700
+
7701
+ auto memberType =
7702
+ cs.getTypeOfMemberReference (cs.getType (fn), method, cs.DC ,
7703
+ /* isDynamicResult*/ false ,
7704
+ FunctionRefKind::DoubleApply,
7705
+ locator).second ;
7706
+ auto methodType = memberType->castTo <AnyFunctionType>();
7707
+
7708
+ // Construct expression referencing the `dynamicallyCall` method.
7709
+ Expr *member =
7710
+ new (ctx) MemberRefExpr (fn, fn->getEndLoc (), ConcreteDeclRef (method),
7711
+ DeclNameLoc (method->getNameLoc ()),
7712
+ /* Implicit*/ true );
7713
+
7714
+ // Construct argument to the method (either an array or dictionary
7715
+ // expression).
7716
+ Expr *argument = nullptr ;
7717
+ if (!useKwargsMethod) {
7718
+ argument = ArrayExpr::create (ctx, SourceLoc (), arg->getElements (),
7719
+ {}, SourceLoc ());
7720
+ } else {
7721
+ SmallVector<Identifier, 4 > names;
7722
+ SmallVector<Expr *, 4 > dictElements;
7723
+ for (unsigned i = 0 , n = arg->getNumElements (); i < n; i++) {
7724
+ Expr *labelExpr =
7725
+ new (ctx) StringLiteralExpr (arg->getElementName (i).get (),
7726
+ arg->getElementNameLoc (i),
7727
+ /* Implicit*/ true );
7728
+ Expr *pair =
7729
+ TupleExpr::createImplicit (ctx, { labelExpr, arg->getElement (i) },
7730
+ {});
7731
+ dictElements.push_back (pair);
7732
+ }
7733
+ argument = DictionaryExpr::create (ctx, SourceLoc (), dictElements, {},
7734
+ SourceLoc ());
7735
+ }
7736
+ argument->setImplicit ();
7737
+
7738
+ // Construct call to the `dynamicallyCall` method.
7739
+ auto argumentName = methodType->getParams ()[0 ].getLabel ();
7740
+ Expr *result = CallExpr::createImplicit (ctx, member, argument,
7741
+ { argumentName });
7742
+ tc.typeCheckExpression (result, dc);
7743
+ cs.cacheExprTypes (result);
7744
+ return result;
7665
7745
}
7666
7746
7667
7747
0 commit comments