@@ -7072,6 +7072,74 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
7072
7072
return literal;
7073
7073
}
7074
7074
7075
+ // Resolve @dynamicCallable applications.
7076
+ static Expr *finishApplyDynamicCallable (ConstraintSystem &cs,
7077
+ const Solution &solution,
7078
+ ApplyExpr *apply,
7079
+ ConstraintLocatorBuilder locator) {
7080
+ auto &ctx = cs.getASTContext ();
7081
+ auto *fn = apply->getFn ();
7082
+
7083
+ TupleExpr *arg = dyn_cast<TupleExpr>(apply->getArg ());
7084
+ if (auto parenExpr = dyn_cast<ParenExpr>(apply->getArg ()))
7085
+ arg = TupleExpr::createImplicit (ctx, parenExpr->getSubExpr (), {});
7086
+
7087
+ // Get resolved `dynamicallyCall` method and verify it.
7088
+ auto loc = locator.withPathElement (ConstraintLocator::ApplyFunction);
7089
+ auto selected = solution.getOverloadChoice (cs.getConstraintLocator (loc));
7090
+ auto *method = dyn_cast<FuncDecl>(selected.choice .getDecl ());
7091
+ auto methodType = selected.openedType ->castTo <AnyFunctionType>();
7092
+ assert (method->getName () == ctx.Id_dynamicallyCall &&
7093
+ " Expected 'dynamicallyCall' method" );
7094
+ assert (methodType->getParams ().size () == 1 &&
7095
+ " Expected 'dynamicallyCall' method with one parameter" );
7096
+ auto argumentLabel = methodType->getParams ()[0 ].getLabel ();
7097
+ assert ((argumentLabel == ctx.Id_withArguments ||
7098
+ argumentLabel == ctx.Id_withKeywordArguments ) &&
7099
+ " Expected 'dynamicallyCall' method argument label 'withArguments' or "
7100
+ " 'withKeywordArguments'" );
7101
+
7102
+ // Determine which method was resolved: a `withArguments` method or a
7103
+ // `withKeywordArguments` method.
7104
+ bool useKwargsMethod = argumentLabel == ctx.Id_withKeywordArguments ;
7105
+
7106
+ // Construct expression referencing the `dynamicallyCall` method.
7107
+ Expr *member =
7108
+ new (ctx) MemberRefExpr (fn, fn->getEndLoc (), ConcreteDeclRef (method),
7109
+ DeclNameLoc (method->getNameLoc ()),
7110
+ /* Implicit*/ true );
7111
+
7112
+ // Construct argument to the method (either an array or dictionary
7113
+ // expression).
7114
+ Expr *argument = nullptr ;
7115
+ if (!useKwargsMethod) {
7116
+ argument = ArrayExpr::create (ctx, SourceLoc (), arg->getElements (),
7117
+ {}, SourceLoc ());
7118
+ } else {
7119
+ SmallVector<Identifier, 4 > names;
7120
+ SmallVector<Expr *, 4 > dictElements;
7121
+ for (unsigned i = 0 , n = arg->getNumElements (); i < n; i++) {
7122
+ Expr *labelExpr =
7123
+ new (ctx) StringLiteralExpr (arg->getElementName (i).get (),
7124
+ arg->getElementNameLoc (i),
7125
+ /* Implicit*/ true );
7126
+ Expr *pair =
7127
+ TupleExpr::createImplicit (ctx, { labelExpr, arg->getElement (i) }, {});
7128
+ dictElements.push_back (pair);
7129
+ }
7130
+ argument = DictionaryExpr::create (ctx, SourceLoc (), dictElements, {},
7131
+ SourceLoc ());
7132
+ }
7133
+ argument->setImplicit ();
7134
+
7135
+ // Construct call to the `dynamicallyCall` method.
7136
+ Expr *result = CallExpr::createImplicit (ctx, member, argument,
7137
+ { argumentLabel });
7138
+ cs.TC .typeCheckExpression (result, cs.DC );
7139
+ cs.cacheExprTypes (result);
7140
+ return result;
7141
+ }
7142
+
7075
7143
Expr *ExprRewriter::finishApply (ApplyExpr *apply, Type openedType,
7076
7144
ConstraintLocatorBuilder locator) {
7077
7145
TypeChecker &tc = cs.getTypeChecker ();
@@ -7366,67 +7434,72 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
7366
7434
}
7367
7435
7368
7436
// We have a type constructor.
7369
- auto metaTy = cs.getType (fn)->castTo <AnyMetatypeType>();
7370
- auto ty = metaTy->getInstanceType ();
7371
-
7372
- if (!cs.isTypeReference (fn)) {
7373
- bool isExistentialType = false ;
7374
- // If this is an attempt to initialize existential type.
7375
- if (auto metaType = cs.getType (fn)->getAs <MetatypeType>()) {
7376
- auto instanceType = metaType->getInstanceType ();
7377
- isExistentialType = instanceType->isExistentialType ();
7378
- }
7379
-
7380
- if (!isExistentialType) {
7381
- // If the metatype value isn't a type expression,
7382
- // the user should reference '.init' explicitly, for clarity.
7383
- cs.TC
7384
- .diagnose (apply->getArg ()->getStartLoc (),
7385
- diag::missing_init_on_metatype_initialization)
7386
- .fixItInsert (apply->getArg ()->getStartLoc (), " .init" );
7387
- }
7388
- }
7389
-
7390
- // If we're "constructing" a tuple type, it's simply a conversion.
7391
- if (auto tupleTy = ty->getAs <TupleType>()) {
7392
- // FIXME: Need an AST to represent this properly.
7393
- return coerceToType (apply->getArg (), tupleTy, locator);
7394
- }
7437
+ if (auto metaTy = cs.getType (fn)->getAs <AnyMetatypeType>()) {
7438
+ auto ty = metaTy->getInstanceType ();
7439
+
7440
+ if (!cs.isTypeReference (fn)) {
7441
+ bool isExistentialType = false ;
7442
+ // If this is an attempt to initialize existential type.
7443
+ if (auto metaType = cs.getType (fn)->getAs <MetatypeType>()) {
7444
+ auto instanceType = metaType->getInstanceType ();
7445
+ isExistentialType = instanceType->isExistentialType ();
7446
+ }
7447
+
7448
+ if (!isExistentialType) {
7449
+ // If the metatype value isn't a type expression,
7450
+ // the user should reference '.init' explicitly, for clarity.
7451
+ cs.TC
7452
+ .diagnose (apply->getArg ()->getStartLoc (),
7453
+ diag::missing_init_on_metatype_initialization)
7454
+ .fixItInsert (apply->getArg ()->getStartLoc (), " .init" );
7455
+ }
7456
+ }
7457
+
7458
+ // If we're "constructing" a tuple type, it's simply a conversion.
7459
+ if (auto tupleTy = ty->getAs <TupleType>()) {
7460
+ // FIXME: Need an AST to represent this properly.
7461
+ return coerceToType (apply->getArg (), tupleTy, locator);
7462
+ }
7463
+
7464
+ // We're constructing a value of nominal type. Look for the constructor or
7465
+ // enum element to use.
7466
+ auto ctorLocator = cs.getConstraintLocator (
7467
+ locator.withPathElement (ConstraintLocator::ApplyFunction)
7468
+ .withPathElement (ConstraintLocator::ConstructorMember));
7469
+ auto selected = solution.getOverloadChoiceIfAvailable (ctorLocator);
7470
+ if (!selected) {
7471
+ assert (ty->hasError () || ty->hasUnresolvedType ());
7472
+ cs.setType (apply, ty);
7473
+ return apply;
7474
+ }
7475
+
7476
+ assert (ty->getNominalOrBoundGenericNominal () || ty->is <DynamicSelfType>() ||
7477
+ ty->isExistentialType () || ty->is <ArchetypeType>());
7478
+
7479
+ // We have the constructor.
7480
+ auto choice = selected->choice ;
7481
+
7482
+ // Consider the constructor decl reference expr 'implicit', but the
7483
+ // constructor call expr itself has the apply's 'implicitness'.
7484
+ bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7485
+ Expr *declRef = buildMemberRef (fn, selected->openedFullType ,
7486
+ /* dotLoc=*/ SourceLoc (), choice,
7487
+ DeclNameLoc (fn->getEndLoc ()),
7488
+ selected->openedType , locator, ctorLocator,
7489
+ /* Implicit=*/ true , choice.getFunctionRefKind (),
7490
+ AccessSemantics::Ordinary, isDynamic);
7491
+ if (!declRef)
7492
+ return nullptr ;
7493
+ declRef->setImplicit (apply->isImplicit ());
7494
+ apply->setFn (declRef);
7395
7495
7396
- // We're constructing a value of nominal type. Look for the constructor or
7397
- // enum element to use.
7398
- auto ctorLocator = cs.getConstraintLocator (
7399
- locator.withPathElement (ConstraintLocator::ApplyFunction)
7400
- .withPathElement (ConstraintLocator::ConstructorMember));
7401
- auto selected = solution.getOverloadChoiceIfAvailable (ctorLocator);
7402
- if (!selected) {
7403
- assert (ty->hasError () || ty->hasUnresolvedType ());
7404
- cs.setType (apply, ty);
7405
- return apply;
7496
+ // Tail-recur to actually call the constructor.
7497
+ return finishApply (apply, openedType, locator);
7406
7498
}
7407
7499
7408
- assert (ty->getNominalOrBoundGenericNominal () || ty->is <DynamicSelfType>() ||
7409
- ty->isExistentialType () || ty->is <ArchetypeType>());
7410
-
7411
- // We have the constructor.
7412
- auto choice = selected->choice ;
7413
-
7414
- // Consider the constructor decl reference expr 'implicit', but the
7415
- // constructor call expr itself has the apply's 'implicitness'.
7416
- bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7417
- Expr *declRef = buildMemberRef (fn, selected->openedFullType ,
7418
- /* dotLoc=*/ SourceLoc (), choice,
7419
- DeclNameLoc (fn->getEndLoc ()),
7420
- selected->openedType , locator, ctorLocator,
7421
- /* Implicit=*/ true , choice.getFunctionRefKind (),
7422
- AccessSemantics::Ordinary, isDynamic);
7423
- if (!declRef)
7424
- return nullptr ;
7425
- declRef->setImplicit (apply->isImplicit ());
7426
- apply->setFn (declRef);
7427
-
7428
- // Tail-recur to actually call the constructor.
7429
- return finishApply (apply, openedType, locator);
7500
+ // Handle @dynamicCallable applications.
7501
+ // At this point, all other ApplyExpr cases have been handled.
7502
+ return finishApplyDynamicCallable (cs, solution, apply, locator);
7430
7503
}
7431
7504
7432
7505
0 commit comments