@@ -7067,6 +7067,9 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
70677067 llvm_unreachable (" Unhandled DeclTypeCheckingSemantics in switch." );
70687068 };
70697069
7070+ // Save the original potentially lvalue function for rewriting call method
7071+ // applications.
7072+ auto *originalFn = fn;
70707073 // The function is always an rvalue.
70717074 fn = cs.coerceToRValue (fn);
70727075
@@ -7213,6 +7216,59 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
72137216 return finishApply (apply, openedType, locator);
72147217 }
72157218
7219+ // Handle call method applications.
7220+ auto &ctx = cs.getASTContext ();
7221+
7222+ TupleExpr *arg = dyn_cast<TupleExpr>(apply->getArg ());
7223+ if (auto parenExpr = dyn_cast<ParenExpr>(apply->getArg ()))
7224+ arg = TupleExpr::createImplicit (ctx, parenExpr->getSubExpr (), {});
7225+
7226+ // Get resolved call method and verify it.
7227+ auto loc = locator.withPathElement (ConstraintLocator::ApplyFunction);
7228+ auto selected = solution.getOverloadChoice (cs.getConstraintLocator (loc));
7229+ auto choice = selected.choice ;
7230+ auto *callMethod = dyn_cast<FuncDecl>(selected.choice .getDecl ());
7231+ if (callMethod && callMethod->isCallable ()) {
7232+ auto methodType =
7233+ simplifyType (selected.openedType )->castTo <AnyFunctionType>();
7234+ auto selfParam = callMethod->getImplicitSelfDecl ();
7235+ // Diagnose `mutating` method call on immutable value.
7236+ // FIXME(TF-444): This logic for `mutating` method calls incorrectly rejects
7237+ // IUOs. Performing this ad-hoc check using `originalFn` feels hacky;
7238+ // rewrite if possible.
7239+ if (!cs.getType (originalFn)->hasLValueType () && selfParam->isInOut ()) {
7240+ AssignmentFailure failure (originalFn, cs, originalFn->getLoc (),
7241+ diag::cannot_pass_rvalue_mutating_subelement,
7242+ diag::cannot_pass_rvalue_mutating);
7243+ failure.diagnose ();
7244+ return nullptr ;
7245+ }
7246+ // Create direct reference to call method.
7247+ bool isDynamic = choice.getKind () == OverloadChoiceKind::DeclViaDynamic;
7248+ Expr *declRef = buildMemberRef (originalFn, selected.openedFullType ,
7249+ /* dotLoc=*/ SourceLoc (), choice,
7250+ DeclNameLoc (fn->getEndLoc ()),
7251+ selected.openedType , loc, loc,
7252+ /* Implicit=*/ true ,
7253+ choice.getFunctionRefKind (),
7254+ AccessSemantics::Ordinary, isDynamic);
7255+ if (!declRef)
7256+ return nullptr ;
7257+ declRef->setImplicit (apply->isImplicit ());
7258+ apply->setFn (declRef);
7259+ // Coerce argument to input type of call method.
7260+ SmallVector<Identifier, 2 > argLabelsScratch;
7261+ auto *arg = coerceCallArguments (apply->getArg (), methodType, apply,
7262+ apply->getArgumentLabels (argLabelsScratch),
7263+ apply->hasTrailingClosure (), loc);
7264+ if (!arg)
7265+ return nullptr ;
7266+ apply->setArg (arg);
7267+ cs.setType (apply, methodType->getResult ());
7268+ cs.cacheExprTypes (apply);
7269+ return apply;
7270+ }
7271+
72167272 // Handle @dynamicCallable applications.
72177273 // At this point, all other ApplyExpr cases have been handled.
72187274 return finishApplyDynamicCallable (cs, solution, apply, locator);
0 commit comments