Skip to content

Commit 8e0ec8d

Browse files
committed
[CS] Allow getCalleeLocator to look through optional chaining
1 parent 52782cf commit 8e0ec8d

File tree

3 files changed

+20
-10
lines changed

3 files changed

+20
-10
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,20 +224,23 @@ FailureDiagnostic::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
224224
if (auto overload = getChoiceFor(anchor)) {
225225
// If we have resolved an overload for the callee, then use that to get the
226226
// function type and callee.
227-
if (auto *decl = overload->choice.getDeclOrNull())
228-
callee = decl;
229-
227+
callee = overload->choice.getDeclOrNull();
230228
rawFnType = overload->openedType;
231229
} else {
232230
// If we didn't resolve an overload for the callee, we must be dealing with
233231
// a call of an arbitrary function expr.
234232
auto *call = cast<CallExpr>(anchor);
235233
assert(!shouldHaveDirectCalleeOverload(call) &&
236234
"Should we have resolved a callee for this?");
237-
rawFnType = cs.getType(call->getFn())->getRValueType();
235+
rawFnType = cs.getType(call->getFn());
238236
}
239237

240-
auto *fnType = resolveType(rawFnType)->getAs<FunctionType>();
238+
// Try to resolve the function type by loading lvalues and looking through
239+
// optional types, which can occur for expressions like `fn?(5)`.
240+
auto *fnType = resolveType(rawFnType)
241+
->getRValueType()
242+
->lookThroughAllOptionalTypes()
243+
->getAs<FunctionType>();
241244
if (!fnType)
242245
return None;
243246

lib/Sema/ConstraintSystem.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,15 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(Expr *expr) {
432432
return getConstraintLocator(fnLocator,
433433
ConstraintLocator::ConstructorMember);
434434
}
435-
// Otherwise fall through and look for locators anchored on the fn expr.
436-
expr = fnExpr->getSemanticsProvidingExpr();
435+
436+
// Otherwise fall through and look for locators anchored on the function
437+
// expr. For CallExprs, this can look through things like parens and
438+
// optional chaining.
439+
if (auto *callExpr = dyn_cast<CallExpr>(expr)) {
440+
expr = callExpr->getDirectCallee();
441+
} else {
442+
expr = fnExpr;
443+
}
437444
}
438445

439446
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {

test/Constraints/optional.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ class A {
1010
@objc(do_b_2:) func do_b(_ x: Int) {}
1111
@objc func do_b(_ x: Float) {}
1212

13-
@objc func do_c(x: Int) {}
14-
@objc func do_c(y: Int) {}
13+
@objc func do_c(x: Int) {} // expected-note {{incorrect labels for candidate (have: '(_:)', expected: '(x:)')}}
14+
@objc func do_c(y: Int) {} // expected-note {{incorrect labels for candidate (have: '(_:)', expected: '(y:)')}}
1515
}
1616

1717
func test0(_ a: AnyObject) {
@@ -20,7 +20,7 @@ func test0(_ a: AnyObject) {
2020
a.do_b?(1)
2121
a.do_b?(5.0)
2222

23-
a.do_c?(1) // expected-error {{cannot invoke value of function type with argument list '(Int)'}}
23+
a.do_c?(1) // expected-error {{no exact matches in call to instance method 'do_c'}}
2424
a.do_c?(x: 1)
2525
}
2626

0 commit comments

Comments
 (0)