Skip to content

Commit aa8d7ba

Browse files
committed
[CS] Apply all finishApply's transforms to callAsFunction
Rather than coercing the call arguments ourselves, just build the finished member reference for the callAsFunction method, and let finishApply do the rest. This allows us to deal with transformations such as IUO unwraps. Resolves SR-11881.
1 parent 4d8e612 commit aa8d7ba

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
lines changed

lib/Sema/CSApply.cpp

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6495,12 +6495,10 @@ static bool isValidDynamicCallableMethod(FuncDecl *method,
64956495
return true;
64966496
}
64976497

6498-
// Resolve `callAsFunction` method applications.
6499-
static Expr *finishApplyCallAsFunctionMethod(
6498+
// Build a reference to a `callAsFunction` method.
6499+
static Expr *buildCallAsFunctionMethodRef(
65006500
ExprRewriter &rewriter, ApplyExpr *apply, SelectedOverload selected,
6501-
AnyFunctionType *openedMethodType,
65026501
ConstraintLocatorBuilder applyFunctionLoc) {
6503-
auto &cs = rewriter.cs;
65046502
auto *fn = apply->getFn();
65056503
auto choice = selected.choice;
65066504
// Create direct reference to `callAsFunction` method.
@@ -6512,21 +6510,7 @@ static Expr *finishApplyCallAsFunctionMethod(
65126510
if (!declRef)
65136511
return nullptr;
65146512
declRef->setImplicit(apply->isImplicit());
6515-
apply->setFn(declRef);
6516-
// Coerce argument to input type of the `callAsFunction` method.
6517-
auto callee = rewriter.resolveConcreteDeclRef(choice.getDecl(),
6518-
applyFunctionLoc);
6519-
SmallVector<Identifier, 2> argLabelsScratch;
6520-
auto *arg = rewriter.coerceCallArguments(
6521-
apply->getArg(), openedMethodType, callee, apply,
6522-
apply->getArgumentLabels(argLabelsScratch), apply->hasTrailingClosure(),
6523-
applyFunctionLoc);
6524-
if (!arg)
6525-
return nullptr;
6526-
apply->setArg(arg);
6527-
cs.setType(apply, openedMethodType->getResult());
6528-
cs.cacheExprTypes(apply);
6529-
return apply;
6513+
return declRef;
65306514
}
65316515

65326516
// Resolve `@dynamicCallable` applications.
@@ -6768,12 +6752,19 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, ConcreteDeclRef callee,
67686752
auto methodType =
67696753
simplifyType(selected->openedType)->getAs<AnyFunctionType>();
67706754
if (method && methodType) {
6771-
if (method->isCallAsFunctionMethod())
6772-
return finishApplyCallAsFunctionMethod(
6773-
*this, apply, *selected, methodType, applyFunctionLoc);
6774-
if (methodType && isValidDynamicCallableMethod(method, methodType))
6755+
// Handle a call to a @dynamicCallable method.
6756+
if (isValidDynamicCallableMethod(method, methodType))
67756757
return finishApplyDynamicCallable(
67766758
apply, *selected, method, methodType, applyFunctionLoc);
6759+
6760+
// If this is an implicit call to a callAsFunction method, build the
6761+
// appropriate member reference.
6762+
if (method->isCallAsFunctionMethod()) {
6763+
fn = buildCallAsFunctionMethodRef(*this, apply, *selected,
6764+
applyFunctionLoc);
6765+
if (!fn)
6766+
return nullptr;
6767+
}
67776768
}
67786769
}
67796770

test/Sema/call_as_function_simple.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,18 @@ func testDefaults(_ x: DoubleANumber) {
204204
x(5)
205205
x(5, completion: { _ in })
206206
}
207+
208+
// SR-11881
209+
struct IUOCallable {
210+
static var callable: IUOCallable { IUOCallable() }
211+
func callAsFunction(_ x: Int) -> IUOCallable! { nil }
212+
}
213+
214+
func testIUOCallAsFunction(_ x: IUOCallable) {
215+
let _: IUOCallable = x(5)
216+
let _: IUOCallable? = x(5)
217+
let _ = x(5)
218+
219+
let _: IUOCallable = .callable(5)
220+
let _: IUOCallable? = .callable(5)
221+
}

0 commit comments

Comments
 (0)