@@ -1068,9 +1068,12 @@ namespace {
1068
1068
Expr *finishApply (ApplyExpr *apply, Type openedType,
1069
1069
ConstraintLocatorBuilder locator);
1070
1070
1071
- // Resolve @dynamicCallable applications.
1072
- Expr *finishApplyDynamicCallable (const Solution &solution, ApplyExpr *apply,
1073
- ConstraintLocatorBuilder locator);
1071
+ // Resolve `@dynamicCallable` applications.
1072
+ Expr *finishApplyDynamicCallable (ApplyExpr *apply,
1073
+ SelectedOverload selected,
1074
+ FuncDecl *method,
1075
+ AnyFunctionType *methodType,
1076
+ ConstraintLocatorBuilder applyFunctionLoc);
1074
1077
1075
1078
private:
1076
1079
// / Simplify the given type by substituting all occurrences of
@@ -6828,11 +6831,62 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
6828
6831
return literal;
6829
6832
}
6830
6833
6831
- // Resolve @dynamicCallable applications.
6834
+ // Returns true if the given method and method type are a valid
6835
+ // `@dynamicCallable` required `func dynamicallyCall` method.
6836
+ static bool isValidDynamicCallableMethod (FuncDecl *method,
6837
+ AnyFunctionType *methodType) {
6838
+ auto &ctx = method->getASTContext ();
6839
+ if (method->getName () != ctx.Id_dynamicallyCall )
6840
+ return false ;
6841
+ if (methodType->getParams ().size () != 1 )
6842
+ return false ;
6843
+ auto argumentLabel = methodType->getParams ()[0 ].getLabel ();
6844
+ if (argumentLabel != ctx.Id_withArguments &&
6845
+ argumentLabel != ctx.Id_withKeywordArguments )
6846
+ return false ;
6847
+ return true ;
6848
+ }
6849
+
6850
+ // Resolve `callAsFunction` method applications.
6851
+ static Expr *finishApplyCallAsFunctionMethod (
6852
+ ExprRewriter &rewriter, ApplyExpr *apply, SelectedOverload selected,
6853
+ AnyFunctionType *openedMethodType,
6854
+ ConstraintLocatorBuilder applyFunctionLoc) {
6855
+ auto &cs = rewriter.cs ;
6856
+ auto *fn = apply->getFn ();
6857
+ auto choice = selected.choice ;
6858
+ // Create direct reference to `callAsFunction` method.
6859
+ bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
6860
+ auto *declRef = rewriter.buildMemberRef (
6861
+ fn, selected.openedFullType , /* dotLoc*/ SourceLoc (), choice,
6862
+ DeclNameLoc (fn->getEndLoc ()), selected.openedType , applyFunctionLoc,
6863
+ applyFunctionLoc, /* implicit*/ true , choice.getFunctionRefKind (),
6864
+ AccessSemantics::Ordinary, isDynamic);
6865
+ if (!declRef)
6866
+ return nullptr ;
6867
+ declRef->setImplicit (apply->isImplicit ());
6868
+ apply->setFn (declRef);
6869
+ // Coerce argument to input type of the `callAsFunction` method.
6870
+ SmallVector<Identifier, 2 > argLabelsScratch;
6871
+ auto *arg = rewriter.coerceCallArguments (
6872
+ apply->getArg (), openedMethodType, apply,
6873
+ apply->getArgumentLabels (argLabelsScratch), apply->hasTrailingClosure (),
6874
+ applyFunctionLoc);
6875
+ if (!arg)
6876
+ return nullptr ;
6877
+ apply->setArg (arg);
6878
+ cs.setType (apply, openedMethodType->getResult ());
6879
+ cs.cacheExprTypes (apply);
6880
+ return apply;
6881
+ }
6882
+
6883
+ // Resolve `@dynamicCallable` applications.
6832
6884
Expr *
6833
- ExprRewriter::finishApplyDynamicCallable (const Solution &solution,
6834
- ApplyExpr *apply,
6835
- ConstraintLocatorBuilder locator) {
6885
+ ExprRewriter::finishApplyDynamicCallable (ApplyExpr *apply,
6886
+ SelectedOverload selected,
6887
+ FuncDecl *method,
6888
+ AnyFunctionType *methodType,
6889
+ ConstraintLocatorBuilder loc) {
6836
6890
auto &ctx = cs.getASTContext ();
6837
6891
auto *fn = apply->getFn ();
6838
6892
@@ -6841,27 +6895,16 @@ ExprRewriter::finishApplyDynamicCallable(const Solution &solution,
6841
6895
arg = TupleExpr::createImplicit (ctx, parenExpr->getSubExpr (), {});
6842
6896
6843
6897
// Get resolved `dynamicallyCall` method and verify it.
6844
- auto loc = locator.withPathElement (ConstraintLocator::ApplyFunction);
6845
- auto selected = solution.getOverloadChoice (cs.getConstraintLocator (loc));
6846
- auto *method = dyn_cast<FuncDecl>(selected.choice .getDecl ());
6847
- auto methodType = simplifyType (selected.openedType )->castTo <AnyFunctionType>();
6848
- assert (method->getName () == ctx.Id_dynamicallyCall &&
6849
- " Expected 'dynamicallyCall' method" );
6898
+ assert (isValidDynamicCallableMethod (method, methodType));
6850
6899
auto params = methodType->getParams ();
6851
- assert (params.size () == 1 &&
6852
- " Expected 'dynamicallyCall' method with one parameter" );
6853
6900
auto argumentType = params[0 ].getParameterType ();
6854
- auto argumentLabel = params[0 ].getLabel ();
6855
- assert ((argumentLabel == ctx.Id_withArguments ||
6856
- argumentLabel == ctx.Id_withKeywordArguments ) &&
6857
- " Expected 'dynamicallyCall' method argument label 'withArguments' or "
6858
- " 'withKeywordArguments'" );
6859
6901
6860
6902
// Determine which method was resolved: a `withArguments` method or a
6861
6903
// `withKeywordArguments` method.
6904
+ auto argumentLabel = methodType->getParams ()[0 ].getLabel ();
6862
6905
bool useKwargsMethod = argumentLabel == ctx.Id_withKeywordArguments ;
6863
6906
6864
- // Construct expression referencing the `dynamicallyCall` method.
6907
+ // Construct expression referencing the `dynamicallyCall` method.
6865
6908
bool isDynamic =
6866
6909
selected.choice .getKind () == OverloadChoiceKind::DeclViaDynamic;
6867
6910
auto member = buildMemberRef (fn, selected.openedFullType ,
@@ -7068,6 +7111,24 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
7068
7111
llvm_unreachable (" Unhandled DeclTypeCheckingSemantics in switch." );
7069
7112
};
7070
7113
7114
+ // Resolve `callAsFunction` and `@dynamicCallable` applications.
7115
+ auto applyFunctionLoc =
7116
+ locator.withPathElement (ConstraintLocator::ApplyFunction);
7117
+ if (auto selected = solution.getOverloadChoiceIfAvailable (
7118
+ cs.getConstraintLocator (applyFunctionLoc))) {
7119
+ auto *method = dyn_cast<FuncDecl>(selected->choice .getDecl ());
7120
+ auto methodType =
7121
+ simplifyType (selected->openedType )->getAs <AnyFunctionType>();
7122
+ if (method && methodType) {
7123
+ if (method->isCallAsFunctionMethod ())
7124
+ return finishApplyCallAsFunctionMethod (
7125
+ *this , apply, *selected, methodType, applyFunctionLoc);
7126
+ if (methodType && isValidDynamicCallableMethod (method, methodType))
7127
+ return finishApplyDynamicCallable (
7128
+ apply, *selected, method, methodType, applyFunctionLoc);
7129
+ }
7130
+ }
7131
+
7071
7132
// The function is always an rvalue.
7072
7133
fn = cs.coerceToRValue (fn);
7073
7134
@@ -7168,57 +7229,51 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
7168
7229
}
7169
7230
7170
7231
// We have a type constructor.
7171
- if (auto metaTy = cs.getType (fn)->getAs <AnyMetatypeType>()) {
7172
- auto ty = metaTy->getInstanceType ();
7173
-
7174
- // If we're "constructing" a tuple type, it's simply a conversion.
7175
- if (auto tupleTy = ty->getAs <TupleType>()) {
7176
- // FIXME: Need an AST to represent this properly.
7177
- return coerceToType (apply->getArg (), tupleTy, locator);
7178
- }
7179
-
7180
- // We're constructing a value of nominal type. Look for the constructor or
7181
- // enum element to use.
7182
- auto ctorLocator = cs.getConstraintLocator (
7183
- locator.withPathElement (ConstraintLocator::ApplyFunction)
7184
- .withPathElement (ConstraintLocator::ConstructorMember));
7185
- auto selected = solution.getOverloadChoiceIfAvailable (ctorLocator);
7186
- if (!selected) {
7187
- assert (ty->hasError () || ty->hasUnresolvedType ());
7188
- cs.setType (apply, ty);
7189
- return apply;
7190
- }
7191
-
7192
- assert (ty->getNominalOrBoundGenericNominal () || ty->is <DynamicSelfType>() ||
7193
- ty->isExistentialType () || ty->is <ArchetypeType>());
7194
-
7195
- // We have the constructor.
7196
- auto choice = selected->choice ;
7197
-
7198
- // Consider the constructor decl reference expr 'implicit', but the
7199
- // constructor call expr itself has the apply's 'implicitness'.
7200
- bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7201
- Expr *declRef = buildMemberRef (fn, selected->openedFullType ,
7202
- /* dotLoc=*/ SourceLoc (), choice,
7203
- DeclNameLoc (fn->getEndLoc ()),
7204
- selected->openedType , locator, ctorLocator,
7205
- /* Implicit=*/ true ,
7206
- choice.getFunctionRefKind (),
7207
- AccessSemantics::Ordinary, isDynamic);
7208
- if (!declRef)
7209
- return nullptr ;
7210
- declRef->setImplicit (apply->isImplicit ());
7211
- apply->setFn (declRef);
7232
+ auto metaTy = cs.getType (fn)->castTo <AnyMetatypeType>();
7233
+ auto ty = metaTy->getInstanceType ();
7212
7234
7213
- // Tail-recur to actually call the constructor.
7214
- return finishApply (apply, openedType, locator);
7235
+ // If we're "constructing" a tuple type, it's simply a conversion.
7236
+ if (auto tupleTy = ty->getAs <TupleType>()) {
7237
+ // FIXME: Need an AST to represent this properly.
7238
+ return coerceToType (apply->getArg (), tupleTy, locator);
7215
7239
}
7216
7240
7217
- // Handle @dynamicCallable applications.
7218
- // At this point, all other ApplyExpr cases have been handled.
7219
- return finishApplyDynamicCallable (solution, apply, locator);
7220
- }
7241
+ // We're constructing a value of nominal type. Look for the constructor or
7242
+ // enum element to use.
7243
+ auto ctorLocator = cs.getConstraintLocator (
7244
+ locator.withPathElement (ConstraintLocator::ApplyFunction)
7245
+ .withPathElement (ConstraintLocator::ConstructorMember));
7246
+ auto selected = solution.getOverloadChoiceIfAvailable (ctorLocator);
7247
+ if (!selected) {
7248
+ assert (ty->hasError () || ty->hasUnresolvedType ());
7249
+ cs.setType (apply, ty);
7250
+ return apply;
7251
+ }
7221
7252
7253
+ assert (ty->getNominalOrBoundGenericNominal () || ty->is <DynamicSelfType>() ||
7254
+ ty->isExistentialType () || ty->is <ArchetypeType>());
7255
+
7256
+ // We have the constructor.
7257
+ auto choice = selected->choice ;
7258
+
7259
+ // Consider the constructor decl reference expr 'implicit', but the
7260
+ // constructor call expr itself has the apply's 'implicitness'.
7261
+ bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7262
+ Expr *declRef = buildMemberRef (fn, selected->openedFullType ,
7263
+ /* dotLoc=*/ SourceLoc (), choice,
7264
+ DeclNameLoc (fn->getEndLoc ()),
7265
+ selected->openedType , locator, ctorLocator,
7266
+ /* Implicit=*/ true ,
7267
+ choice.getFunctionRefKind (),
7268
+ AccessSemantics::Ordinary, isDynamic);
7269
+ if (!declRef)
7270
+ return nullptr ;
7271
+ declRef->setImplicit (apply->isImplicit ());
7272
+ apply->setFn (declRef);
7273
+
7274
+ // Tail-recur to actually call the constructor.
7275
+ return finishApply (apply, openedType, locator);
7276
+ }
7222
7277
7223
7278
// Return the precedence-yielding parent of 'expr', along with the index of
7224
7279
// 'expr' as the child of that parent. The precedence-yielding parent is the
0 commit comments