@@ -7046,6 +7046,74 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
70467046 return literal;
70477047}
70487048
7049+ // Resolve @dynamicCallable applications.
7050+ static Expr *finishApplyDynamicCallable (ConstraintSystem &cs,
7051+ const Solution &solution,
7052+ ApplyExpr *apply,
7053+ ConstraintLocatorBuilder locator) {
7054+ auto &ctx = cs.getASTContext ();
7055+ auto *fn = apply->getFn ();
7056+
7057+ TupleExpr *arg = dyn_cast<TupleExpr>(apply->getArg ());
7058+ if (auto parenExpr = dyn_cast<ParenExpr>(apply->getArg ()))
7059+ arg = TupleExpr::createImplicit (ctx, parenExpr->getSubExpr (), {});
7060+
7061+ // Get resolved `dynamicallyCall` method and verify it.
7062+ auto loc = locator.withPathElement (ConstraintLocator::ApplyFunction);
7063+ auto selected = solution.getOverloadChoice (cs.getConstraintLocator (loc));
7064+ auto *method = dyn_cast<FuncDecl>(selected.choice .getDecl ());
7065+ auto methodType = selected.openedType ->castTo <AnyFunctionType>();
7066+ assert (method->getName () == ctx.Id_dynamicallyCall &&
7067+ " Expected 'dynamicallyCall' method" );
7068+ assert (methodType->getParams ().size () == 1 &&
7069+ " Expected 'dynamicallyCall' method with one parameter" );
7070+ auto argumentLabel = methodType->getParams ()[0 ].getLabel ();
7071+ assert ((argumentLabel == ctx.Id_withArguments ||
7072+ argumentLabel == ctx.Id_withKeywordArguments ) &&
7073+ " Expected 'dynamicallyCall' method argument label 'withArguments' or "
7074+ " 'withKeywordArguments'" );
7075+
7076+ // Determine which method was resolved: a `withArguments` method or a
7077+ // `withKeywordArguments` method.
7078+ bool useKwargsMethod = argumentLabel == ctx.Id_withKeywordArguments ;
7079+
7080+ // Construct expression referencing the `dynamicallyCall` method.
7081+ Expr *member =
7082+ new (ctx) MemberRefExpr (fn, fn->getEndLoc (), ConcreteDeclRef (method),
7083+ DeclNameLoc (method->getNameLoc ()),
7084+ /* Implicit*/ true );
7085+
7086+ // Construct argument to the method (either an array or dictionary
7087+ // expression).
7088+ Expr *argument = nullptr ;
7089+ if (!useKwargsMethod) {
7090+ argument = ArrayExpr::create (ctx, SourceLoc (), arg->getElements (),
7091+ {}, SourceLoc ());
7092+ } else {
7093+ SmallVector<Identifier, 4 > names;
7094+ SmallVector<Expr *, 4 > dictElements;
7095+ for (unsigned i = 0 , n = arg->getNumElements (); i < n; i++) {
7096+ Expr *labelExpr =
7097+ new (ctx) StringLiteralExpr (arg->getElementName (i).get (),
7098+ arg->getElementNameLoc (i),
7099+ /* Implicit*/ true );
7100+ Expr *pair =
7101+ TupleExpr::createImplicit (ctx, { labelExpr, arg->getElement (i) }, {});
7102+ dictElements.push_back (pair);
7103+ }
7104+ argument = DictionaryExpr::create (ctx, SourceLoc (), dictElements, {},
7105+ SourceLoc ());
7106+ }
7107+ argument->setImplicit ();
7108+
7109+ // Construct call to the `dynamicallyCall` method.
7110+ Expr *result = CallExpr::createImplicit (ctx, member, argument,
7111+ { argumentLabel });
7112+ cs.TC .typeCheckExpression (result, cs.DC );
7113+ cs.cacheExprTypes (result);
7114+ return result;
7115+ }
7116+
70497117Expr *ExprRewriter::finishApply (ApplyExpr *apply, Type openedType,
70507118 ConstraintLocatorBuilder locator) {
70517119 TypeChecker &tc = cs.getTypeChecker ();
@@ -7340,67 +7408,73 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
73407408 }
73417409
73427410 // We have a type constructor.
7343- auto metaTy = cs.getType (fn)->castTo <AnyMetatypeType>();
7344- auto ty = metaTy->getInstanceType ();
7345-
7346- if (!cs.isTypeReference (fn)) {
7347- bool isExistentialType = false ;
7348- // If this is an attempt to initialize existential type.
7349- if (auto metaType = cs.getType (fn)->getAs <MetatypeType>()) {
7350- auto instanceType = metaType->getInstanceType ();
7351- isExistentialType = instanceType->isExistentialType ();
7352- }
7353-
7354- if (!isExistentialType) {
7355- // If the metatype value isn't a type expression,
7356- // the user should reference '.init' explicitly, for clarity.
7357- cs.TC
7358- .diagnose (apply->getArg ()->getStartLoc (),
7359- diag::missing_init_on_metatype_initialization)
7360- .fixItInsert (apply->getArg ()->getStartLoc (), " .init" );
7361- }
7362- }
7363-
7364- // If we're "constructing" a tuple type, it's simply a conversion.
7365- if (auto tupleTy = ty->getAs <TupleType>()) {
7366- // FIXME: Need an AST to represent this properly.
7367- return coerceToType (apply->getArg (), tupleTy, locator);
7368- }
7411+ if (auto metaTy = cs.getType (fn)->getAs <AnyMetatypeType>()) {
7412+ auto ty = metaTy->getInstanceType ();
7413+
7414+ if (!cs.isTypeReference (fn)) {
7415+ bool isExistentialType = false ;
7416+ // If this is an attempt to initialize existential type.
7417+ if (auto metaType = cs.getType (fn)->getAs <MetatypeType>()) {
7418+ auto instanceType = metaType->getInstanceType ();
7419+ isExistentialType = instanceType->isExistentialType ();
7420+ }
7421+
7422+ if (!isExistentialType) {
7423+ // If the metatype value isn't a type expression,
7424+ // the user should reference '.init' explicitly, for clarity.
7425+ cs.TC
7426+ .diagnose (apply->getArg ()->getStartLoc (),
7427+ diag::missing_init_on_metatype_initialization)
7428+ .fixItInsert (apply->getArg ()->getStartLoc (), " .init" );
7429+ }
7430+ }
7431+
7432+ // If we're "constructing" a tuple type, it's simply a conversion.
7433+ if (auto tupleTy = ty->getAs <TupleType>()) {
7434+ // FIXME: Need an AST to represent this properly.
7435+ return coerceToType (apply->getArg (), tupleTy, locator);
7436+ }
7437+
7438+ // We're constructing a value of nominal type. Look for the constructor or
7439+ // enum element to use.
7440+ auto ctorLocator = cs.getConstraintLocator (
7441+ locator.withPathElement (ConstraintLocator::ApplyFunction)
7442+ .withPathElement (ConstraintLocator::ConstructorMember));
7443+ auto selected = solution.getOverloadChoiceIfAvailable (ctorLocator);
7444+ if (!selected) {
7445+ assert (ty->hasError () || ty->hasUnresolvedType ());
7446+ cs.setType (apply, ty);
7447+ return apply;
7448+ }
7449+
7450+ assert (ty->getNominalOrBoundGenericNominal () || ty->is <DynamicSelfType>() ||
7451+ ty->isExistentialType () || ty->is <ArchetypeType>());
7452+
7453+ // We have the constructor.
7454+ auto choice = selected->choice ;
7455+
7456+ // Consider the constructor decl reference expr 'implicit', but the
7457+ // constructor call expr itself has the apply's 'implicitness'.
7458+ bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7459+ Expr *declRef = buildMemberRef (fn, selected->openedFullType ,
7460+ /* dotLoc=*/ SourceLoc (), choice,
7461+ DeclNameLoc (fn->getEndLoc ()),
7462+ selected->openedType , locator, ctorLocator,
7463+ /* Implicit=*/ true ,
7464+ choice.getFunctionRefKind (),
7465+ AccessSemantics::Ordinary, isDynamic);
7466+ if (!declRef)
7467+ return nullptr ;
7468+ declRef->setImplicit (apply->isImplicit ());
7469+ apply->setFn (declRef);
73697470
7370- // We're constructing a value of nominal type. Look for the constructor or
7371- // enum element to use.
7372- auto ctorLocator = cs.getConstraintLocator (
7373- locator.withPathElement (ConstraintLocator::ApplyFunction)
7374- .withPathElement (ConstraintLocator::ConstructorMember));
7375- auto selected = solution.getOverloadChoiceIfAvailable (ctorLocator);
7376- if (!selected) {
7377- assert (ty->hasError () || ty->hasUnresolvedType ());
7378- cs.setType (apply, ty);
7379- return apply;
7471+ // Tail-recur to actually call the constructor.
7472+ return finishApply (apply, openedType, locator);
73807473 }
73817474
7382- assert (ty->getNominalOrBoundGenericNominal () || ty->is <DynamicSelfType>() ||
7383- ty->isExistentialType () || ty->is <ArchetypeType>());
7384-
7385- // We have the constructor.
7386- auto choice = selected->choice ;
7387-
7388- // Consider the constructor decl reference expr 'implicit', but the
7389- // constructor call expr itself has the apply's 'implicitness'.
7390- bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7391- Expr *declRef = buildMemberRef (fn, selected->openedFullType ,
7392- /* dotLoc=*/ SourceLoc (), choice,
7393- DeclNameLoc (fn->getEndLoc ()),
7394- selected->openedType , locator, ctorLocator,
7395- /* Implicit=*/ true , choice.getFunctionRefKind (),
7396- AccessSemantics::Ordinary, isDynamic);
7397- if (!declRef)
7398- return nullptr ;
7399- declRef->setImplicit (apply->isImplicit ());
7400- apply->setFn (declRef);
7401-
7402- // Tail-recur to actually call the constructor.
7403- return finishApply (apply, openedType, locator);
7475+ // Handle @dynamicCallable applications.
7476+ // At this point, all other ApplyExpr cases have been handled.
7477+ return finishApplyDynamicCallable (cs, solution, apply, locator);
74047478}
74057479
74067480
0 commit comments