Skip to content

Commit 603d5d6

Browse files
committed
[Constraint solver] Synchronize argument label setting/retrievable.
The walker that was setting argument labels was looking through ! and ? postfix expressions, but the lookup code itself was not, leading to missed opportunities for filtering based on argument labels. Generalize the transformation that maps from the function expression down to the locator for which we will retrieve argument labels.
1 parent 233cf6f commit 603d5d6

File tree

4 files changed

+53
-23
lines changed

4 files changed

+53
-23
lines changed

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3582,22 +3582,7 @@ namespace {
35823582

35833583
void associateArgumentLabels(Expr *fn, State labels,
35843584
bool labelsArePermanent) {
3585-
// Dig out the function, looking through, parentheses, ?, and !.
3586-
do {
3587-
fn = fn->getSemanticsProvidingExpr();
3588-
3589-
if (auto force = dyn_cast<ForceValueExpr>(fn)) {
3590-
fn = force->getSubExpr();
3591-
continue;
3592-
}
3593-
3594-
if (auto bind = dyn_cast<BindOptionalExpr>(fn)) {
3595-
fn = bind->getSubExpr();
3596-
continue;
3597-
}
3598-
3599-
break;
3600-
} while (true);
3585+
fn = getArgumentLabelTargetExpr(fn);
36013586

36023587
// Record the labels.
36033588
if (!labelsArePermanent)

lib/Sema/CSSimplify.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,25 @@ bool constraints::areConservativelyCompatibleArgumentLabels(
139139
decl, hasCurriedSelf, labels, hasTrailingClosure);
140140
}
141141

142+
Expr *constraints::getArgumentLabelTargetExpr(Expr *fn) {
143+
// Dig out the function, looking through, parentheses, ?, and !.
144+
do {
145+
fn = fn->getSemanticsProvidingExpr();
146+
147+
if (auto force = dyn_cast<ForceValueExpr>(fn)) {
148+
fn = force->getSubExpr();
149+
continue;
150+
}
151+
152+
if (auto bind = dyn_cast<BindOptionalExpr>(fn)) {
153+
fn = bind->getSubExpr();
154+
continue;
155+
}
156+
157+
return fn;
158+
} while (true);
159+
}
160+
142161
bool constraints::
143162
areConservativelyCompatibleArgumentLabels(ValueDecl *decl,
144163
bool hasCurriedSelf,
@@ -3289,13 +3308,6 @@ getArgumentLabels(ConstraintSystem &cs, ConstraintLocatorBuilder locator) {
32893308
}
32903309

32913310
if (parts.back().getKind() == ConstraintLocator::ConstructorMember) {
3292-
// FIXME: Workaround for strange anchor on ConstructorMember locators.
3293-
3294-
if (auto optionalWrapper = dyn_cast<BindOptionalExpr>(anchor))
3295-
anchor = optionalWrapper->getSubExpr();
3296-
else if (auto forceWrapper = dyn_cast<ForceValueExpr>(anchor))
3297-
anchor = forceWrapper->getSubExpr();
3298-
32993311
parts.pop_back();
33003312
continue;
33013313
}
@@ -3306,6 +3318,7 @@ getArgumentLabels(ConstraintSystem &cs, ConstraintLocatorBuilder locator) {
33063318
if (!parts.empty())
33073319
return None;
33083320

3321+
anchor = getArgumentLabelTargetExpr(anchor);
33093322
auto known = cs.ArgumentLabels.find(cs.getConstraintLocator(anchor));
33103323
if (known == cs.ArgumentLabels.end())
33113324
return None;

lib/Sema/ConstraintSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,6 +3544,10 @@ matchCallArguments(ConstraintSystem &cs,
35443544
ArrayRef<AnyFunctionType::Param> params,
35453545
ConstraintLocatorBuilder locator);
35463546

3547+
/// Given an expression that is the target of argument labels (for a call,
3548+
/// subscript, etc.), find the underlying target expression.
3549+
Expr *getArgumentLabelTargetExpr(Expr *fn);
3550+
35473551
/// Attempt to prove that arguments with the given labels at the
35483552
/// given parameter depth cannot be used with the given value.
35493553
/// If this cannot be proven, conservatively returns true.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s -debug-constraints 2>%t.err
2+
// RUN: %FileCheck %s < %t.err
3+
4+
// REQUIRES: objc_interop
5+
6+
// This test ensures that we are filtering out overloads based on argument
7+
// labels, arity, etc., before those terms are visited.
8+
9+
import Foundation
10+
11+
@objc protocol P {
12+
func foo(_ i: Int) -> Int
13+
func foo(_ d: Double) -> Int
14+
15+
@objc optional func opt(_ i: Int) -> Int
16+
@objc optional func opt(double: Double) -> Int
17+
18+
subscript(i: Int) -> String { get }
19+
}
20+
21+
func testOptional(obj: P) {
22+
// FIXME: When we remove argument-label filtering from member name lookup,
23+
// this will start failing and need to be replaced with "disabled disjunction
24+
// term".
25+
//
26+
// CHECK-NOT: disjunction
27+
_ = obj.opt?(1)
28+
}

0 commit comments

Comments
 (0)