Skip to content

Commit 7654afd

Browse files
committed
[CSBindings] Delay inference through OptionalObject if "object" is l-value capable
Inference cannot be allowed in cases where both sides are type variables and optional type is l-value capable because it results in binding "optional" to an optional type and later discovering a contextual type that is l-value optional i.e. if "optional type" is resolved by selecting subscript overload.
1 parent cfe2728 commit 7654afd

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1713,6 +1713,26 @@ PotentialBindings::inferFromRelational(Constraint *constraint) {
17131713
/// those types should be opened.
17141714
void PotentialBindings::infer(Constraint *constraint) {
17151715
switch (constraint->getKind()) {
1716+
case ConstraintKind::OptionalObject: {
1717+
// Inference through optional object is allowed if
1718+
// one of the types is resolved or "optional" type variable
1719+
// cannot be bound to l-value, otherwise there is a
1720+
// risk of binding "optional" to an optional type (inferred from
1721+
// the "object") and discovering an l-value binding for it later.
1722+
auto optionalType = constraint->getFirstType();
1723+
1724+
if (auto *optionalVar = optionalType->getAs<TypeVariableType>()) {
1725+
if (optionalVar->getImpl().canBindToLValue()) {
1726+
auto objectType =
1727+
constraint->getSecondType()->lookThroughAllOptionalTypes();
1728+
if (objectType->isTypeVariableOrMember())
1729+
return;
1730+
}
1731+
}
1732+
1733+
LLVM_FALLTHROUGH;
1734+
}
1735+
17161736
case ConstraintKind::Bind:
17171737
case ConstraintKind::Equal:
17181738
case ConstraintKind::BindParam:
@@ -1722,7 +1742,6 @@ void PotentialBindings::infer(Constraint *constraint) {
17221742
case ConstraintKind::Conversion:
17231743
case ConstraintKind::ArgumentConversion:
17241744
case ConstraintKind::OperatorArgumentConversion:
1725-
case ConstraintKind::OptionalObject:
17261745
case ConstraintKind::UnresolvedMemberChainBase: {
17271746
auto binding = inferFromRelational(constraint);
17281747
if (!binding)

test/Constraints/diagnostics.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,9 +1123,11 @@ func rdar17170728() {
11231123
var j: Int?
11241124
var k: Int? = 2
11251125

1126-
let _ = [i, j, k].reduce(0 as Int?) {
1126+
let _ = [i, j, k].reduce(0 as Int?) { // expected-error {{missing argument label 'into:' in call}}
1127+
// expected-error@-1 {{cannot convert value of type 'Int?' to expected argument type '(inout @escaping (Bool, Bool) -> Bool?, Int?) throws -> ()'}}
11271128
$0 && $1 ? $0! + $1! : ($0 ? $0! : ($1 ? $1! : nil))
1128-
// expected-error@-1 4 {{optional type 'Int?' cannot be used as a boolean; test for '!= nil' instead}}
1129+
// expected-error@-1 {{binary operator '+' cannot be applied to two 'Bool' operands}}
1130+
// expected-error@-2 4 {{cannot force unwrap value of non-optional type 'Bool'}}
11291131
}
11301132

11311133
let _ = [i, j, k].reduce(0 as Int?) { // expected-error {{missing argument label 'into:' in call}}
@@ -1556,18 +1558,17 @@ func testNilCoalescingOperatorRemoveFix() {
15561558
let _ = "" /* This is a comment */ ?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{13-43=}}
15571559

15581560
let _ = "" // This is a comment
1559-
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1558:13-1559:10=}}
1561+
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1560:13-1561:10=}}
15601562

15611563
let _ = "" // This is a comment
15621564
/*
15631565
* The blank line below is part of the test case, do not delete it
15641566
*/
1567+
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1563:13-1567:10=}}
15651568

1566-
?? "" // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1561:13-1566:10=}}
1567-
1568-
if ("" ?? // This is a comment // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{9-1569:9=}}
1569+
if ("" ?? // This is a comment // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{9-1570:9=}}
15691570
"").isEmpty {}
15701571

15711572
if ("" // This is a comment
1572-
?? "").isEmpty {} // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1571:9-1572:12=}}
1573+
?? "").isEmpty {} // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}} {{1572:9-1573:12=}}
15731574
}

0 commit comments

Comments
 (0)