Skip to content

Commit a962f02

Browse files
committed
[CS] Associate arg labels for key path subscripts
Change `associateArgumentLabels` to take a locator argument to enable the recording of argument labels for individual key path components. Then move the association of argument labels for subscripts to `addSubscriptConstraints`, and plumb through the argument labels for key path subscript components. This then allows us to correctly ignore choices with mismatching argument labels while solving in certain cases. Resolves SR-11438.
1 parent 04ae94f commit a962f02

File tree

2 files changed

+29
-29
lines changed

2 files changed

+29
-29
lines changed

lib/Sema/CSGen.cpp

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -982,8 +982,8 @@ namespace {
982982
/// Add constraints for a subscript operation.
983983
Type addSubscriptConstraints(
984984
Expr *anchor, Type baseTy, Expr *index,
985-
ValueDecl *declOrNull,
986-
ConstraintLocator *locator = nullptr,
985+
ValueDecl *declOrNull, ArrayRef<Identifier> argLabels,
986+
bool hasTrailingClosure, ConstraintLocator *locator = nullptr,
987987
SmallVectorImpl<TypeVariableType *> *addedTypeVars = nullptr) {
988988
// Locators used in this expression.
989989
if (locator == nullptr)
@@ -999,6 +999,8 @@ namespace {
999999
CS.getConstraintLocator(locator,
10001000
ConstraintLocator::FunctionResult);
10011001

1002+
associateArgumentLabels(memberLocator, {argLabels, hasTrailingClosure});
1003+
10021004
Type outputTy;
10031005

10041006
// For an integer subscript expression on an array slice type, instead of
@@ -1229,8 +1231,9 @@ namespace {
12291231
}
12301232

12311233
Type visitObjectLiteralExpr(ObjectLiteralExpr *expr) {
1234+
auto *exprLoc = CS.getConstraintLocator(expr);
12321235
associateArgumentLabels(
1233-
expr, {expr->getArgumentLabels(), expr->hasTrailingClosure()});
1236+
exprLoc, {expr->getArgumentLabels(), expr->hasTrailingClosure()});
12341237

12351238
// If the expression has already been assigned a type; just use that type.
12361239
if (expr->getType())
@@ -1244,13 +1247,13 @@ namespace {
12441247
return nullptr;
12451248
}
12461249

1247-
auto tv = CS.createTypeVariable(CS.getConstraintLocator(expr),
1250+
auto tv = CS.createTypeVariable(exprLoc,
12481251
TVO_PrefersSubtypeBinding |
12491252
TVO_CanBindToNoEscape);
12501253

12511254
CS.addConstraint(ConstraintKind::LiteralConformsTo, tv,
12521255
protocol->getDeclaredType(),
1253-
CS.getConstraintLocator(expr));
1256+
exprLoc);
12541257

12551258
// The arguments are required to be argument-convertible to the
12561259
// idealized parameter type of the initializer, which generally
@@ -1511,7 +1514,8 @@ namespace {
15111514
CS.getConstraintLocator(expr, ConstraintLocator::ApplyFunction));
15121515

15131516
associateArgumentLabels(
1514-
expr, {expr->getArgumentLabels(), expr->hasTrailingClosure()});
1517+
CS.getConstraintLocator(expr),
1518+
{expr->getArgumentLabels(), expr->hasTrailingClosure()});
15151519
return baseTy;
15161520
}
15171521

@@ -1746,12 +1750,10 @@ namespace {
17461750
return Type();
17471751
}
17481752

1749-
associateArgumentLabels(
1750-
expr, {expr->getArgumentLabels(), expr->hasTrailingClosure()});
1751-
17521753
return addSubscriptConstraints(expr, CS.getType(expr->getBase()),
17531754
expr->getIndex(),
1754-
decl);
1755+
decl, expr->getArgumentLabels(),
1756+
expr->hasTrailingClosure());
17551757
}
17561758

17571759
Type visitArrayExpr(ArrayExpr *expr) {
@@ -1995,10 +1997,10 @@ namespace {
19951997
}
19961998

19971999
Type visitDynamicSubscriptExpr(DynamicSubscriptExpr *expr) {
1998-
associateArgumentLabels(
1999-
expr, {expr->getArgumentLabels(), expr->hasTrailingClosure()});
20002000
return addSubscriptConstraints(expr, CS.getType(expr->getBase()),
2001-
expr->getIndex(), nullptr);
2001+
expr->getIndex(), /*decl*/ nullptr,
2002+
expr->getArgumentLabels(),
2003+
expr->hasTrailingClosure());
20022004
}
20032005

20042006
Type visitTupleElementExpr(TupleElementExpr *expr) {
@@ -2488,7 +2490,8 @@ namespace {
24882490

24892491
SmallVector<Identifier, 4> scratch;
24902492
associateArgumentLabels(
2491-
expr, {expr->getArgumentLabels(scratch), expr->hasTrailingClosure()},
2493+
CS.getConstraintLocator(expr),
2494+
{expr->getArgumentLabels(scratch), expr->hasTrailingClosure()},
24922495
/*labelsArePermanent=*/isa<CallExpr>(expr));
24932496

24942497
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(fnExpr)) {
@@ -3017,7 +3020,10 @@ namespace {
30173020
// re-type-check the constraints during failure diagnosis.
30183021
case KeyPathExpr::Component::Kind::Subscript: {
30193022
base = addSubscriptConstraints(E, base, component.getIndexExpr(),
3020-
/*decl*/ nullptr, memberLocator,
3023+
/*decl*/ nullptr,
3024+
component.getSubscriptLabels(),
3025+
/*hasTrailingClosure*/ false,
3026+
memberLocator,
30213027
&componentTypeVars);
30223028
break;
30233029
}
@@ -3251,15 +3257,13 @@ namespace {
32513257
llvm_unreachable("unhandled operation");
32523258
}
32533259

3254-
void associateArgumentLabels(Expr *expr,
3260+
void associateArgumentLabels(ConstraintLocator *locator,
32553261
ConstraintSystem::ArgumentInfo info,
32563262
bool labelsArePermanent = true) {
3257-
assert(expr);
3263+
assert(locator && locator->getAnchor());
32583264
// Record the labels.
32593265
if (!labelsArePermanent)
32603266
info.Labels = CS.allocateCopy(info.Labels);
3261-
3262-
auto *locator = CS.getConstraintLocator(expr);
32633267
CS.ArgumentInfos[CS.getArgumentInfoLocator(locator)] = info;
32643268
}
32653269
};

test/expr/unary/keypath/keypath.swift

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -541,31 +541,27 @@ func testImplicitConversionInSubscriptIndex() {
541541
_ = \BassSubscript.["hello"] // expected-error{{must be Hashable}}
542542
}
543543

544-
// Crash in diagnostics
545-
struct AmbiguousSubscript {
544+
// Crash in diagnostics + SR-11438
545+
struct UnambiguousSubscript {
546546
subscript(sub: Sub) -> Int { get { } set { } }
547-
// expected-note@-1 {{'subscript(_:)' declared here}}
548-
549547
subscript(y y: Sub) -> Int { get { } set { } }
550-
// expected-note@-1 {{'subscript(y:)' declared here}}
551548
}
552549

553-
func useAmbiguousSubscript(_ sub: Sub) {
554-
let _: PartialKeyPath<AmbiguousSubscript> = \.[sub]
555-
// expected-error@-1 {{ambiguous reference to member 'subscript'}}
550+
func useUnambiguousSubscript(_ sub: Sub) {
551+
let _: PartialKeyPath<UnambiguousSubscript> = \.[sub]
556552
}
557553

558554
struct BothUnavailableSubscript {
559555
@available(*, unavailable)
560-
subscript(sub: Sub) -> Int { get { } set { } }
556+
subscript(sub: Sub) -> Int { get { } set { } } // expected-note {{'subscript(_:)' has been explicitly marked unavailable here}}
561557

562558
@available(*, unavailable)
563559
subscript(y y: Sub) -> Int { get { } set { } }
564560
}
565561

566562
func useBothUnavailableSubscript(_ sub: Sub) {
567563
let _: PartialKeyPath<BothUnavailableSubscript> = \.[sub]
568-
// expected-error@-1 {{type of expression is ambiguous without more context}}
564+
// expected-error@-1 {{'subscript(_:)' is unavailable}}
569565
}
570566

571567
// SR-6106

0 commit comments

Comments
 (0)