Skip to content

Commit c8e1479

Browse files
committed
[ConstraintSystem] Move missing contextual protocol detection to matchExistentialTypes
(cherry picked from commit 17643a3)
1 parent 0b2ce5c commit c8e1479

File tree

9 files changed

+59
-22
lines changed

9 files changed

+59
-22
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2378,8 +2378,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
23782378

23792379
// When complaining about conversion to a protocol type, complain about
23802380
// conformance instead of "conversion".
2381-
if (contextualType->is<ProtocolType>() ||
2382-
contextualType->is<ProtocolCompositionType>()) {
2381+
if (contextualType->isExistentialType()) {
23832382
MissingContextualConformanceFailure failure(
23842383
expr, CS, CTP, exprType, contextualType,
23852384
CS.getConstraintLocator(expr, ConstraintLocator::ContextualType));

lib/Sema/CSDiagnostics.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2831,10 +2831,28 @@ bool MissingContextualConformanceFailure::diagnoseAsError() {
28312831
assert(Context != CTP_Unused);
28322832
diagnostic = getDiagnosticFor(Context);
28332833
break;
2834+
2835+
default:
2836+
break;
28342837
}
28352838
}
28362839

2837-
emitDiagnostic(anchor->getLoc(), *diagnostic, getFromType(), getToType());
2840+
if (!diagnostic)
2841+
return false;
2842+
2843+
auto srcType = getFromType();
2844+
auto dstType = getToType();
2845+
2846+
emitDiagnostic(anchor->getLoc(), *diagnostic, srcType, dstType);
2847+
2848+
if (isa<InOutExpr>(anchor))
2849+
return true;
2850+
2851+
if (srcType->isAny() && dstType->isAnyObject()) {
2852+
emitDiagnostic(anchor->getLoc(), diag::any_as_anyobject_fixit)
2853+
.fixItInsertAfter(anchor->getEndLoc(), " as AnyObject");
2854+
}
2855+
28382856
return true;
28392857
}
28402858

lib/Sema/CSSimplify.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,8 +1731,28 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
17311731
case SolutionKind::Unsolved:
17321732
break;
17331733

1734-
case SolutionKind::Error:
1735-
return getTypeMatchFailure(locator);
1734+
case SolutionKind::Error: {
1735+
if (!shouldAttemptFixes())
1736+
return getTypeMatchFailure(locator);
1737+
1738+
if (auto last = locator.last()) {
1739+
// TODO(diagnostics): Diagnosing missing conformances
1740+
// associated with arguments requires having general
1741+
// conversion failures implemented first, otherwise
1742+
// we would be misdiagnosing ambiguous cases associated
1743+
// with overloaded declarations.
1744+
if (last->getKind() == ConstraintLocator::ApplyArgToParam)
1745+
return getTypeMatchFailure(locator);
1746+
}
1747+
1748+
auto *fix = MissingConformance::forContextual(
1749+
*this, type1, proto, getConstraintLocator(locator));
1750+
1751+
if (recordFix(fix))
1752+
return getTypeMatchFailure(locator);
1753+
1754+
break;
1755+
}
17361756
}
17371757
}
17381758

@@ -2003,12 +2023,8 @@ bool ConstraintSystem::repairFailures(
20032023
return false;
20042024
};
20052025

2006-
auto repairByAddingConformance = [&](Type lhs, Type rhs) -> bool {
2007-
if (lhs->isTypeVariableOrMember())
2008-
return false;
2009-
2010-
if (rhs->isAny() ||
2011-
!(rhs->is<ProtocolType>() || rhs->is<ProtocolCompositionType>()))
2026+
auto repairByAnyToAnyObjectCast = [&](Type lhs, Type rhs) -> bool {
2027+
if (!(lhs->isAny() && rhs->isAnyObject()))
20122028
return false;
20132029

20142030
conversionsOrFixes.push_back(MissingConformance::forContextual(
@@ -2035,14 +2051,14 @@ bool ConstraintSystem::repairFailures(
20352051
if (repairByInsertingExplicitCall(lhs, rhs))
20362052
return true;
20372053

2038-
if (repairByAddingConformance(lhs, rhs))
2039-
return true;
2040-
20412054
if (isa<InOutExpr>(AE->getSrc())) {
20422055
conversionsOrFixes.push_back(
20432056
RemoveAddressOf::create(*this, getConstraintLocator(locator)));
20442057
return true;
20452058
}
2059+
2060+
if (repairByAnyToAnyObjectCast(lhs, rhs))
2061+
return true;
20462062
}
20472063

20482064
return false;
@@ -2129,7 +2145,7 @@ bool ConstraintSystem::repairFailures(
21292145
if (repairByInsertingExplicitCall(lhs, rhs))
21302146
return true;
21312147

2132-
if (repairByAddingConformance(lhs, rhs))
2148+
if (repairByAnyToAnyObjectCast(lhs, rhs))
21332149
return true;
21342150

21352151
// If both types are key path, the only differences

test/ClangImporter/objc_parse.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func testProtocols(_ b: B, bp: BProto) {
201201
var c1 : Cat1Proto = b
202202
var bcat1 = b.getAsProtoWithCat()!
203203
c1 = bcat1
204-
bcat1 = c1 // expected-error{{value of type 'Cat1Proto' does not conform to 'BProto & Cat1Proto' in assignment}}
204+
bcat1 = c1 // expected-error{{value of type 'Cat1Proto' does not conform to 'BProto' in assignment}}
205205
}
206206

207207
// Methods only defined in a protocol

test/Constraints/bridging.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ func forceUniversalBridgeToAnyObject<T, U: KnownClassProtocol>(a: T, b: U, c: An
349349

350350
z = a // expected-error{{does not conform to 'AnyObject'}}
351351
z = b
352-
z = c // expected-error{{does not conform to 'AnyObject'}}
352+
z = c // expected-error{{does not conform to 'AnyObject'}} expected-note {{cast 'Any' to 'AnyObject'}} {{8-8= as AnyObject}}
353353
z = d // expected-error{{does not conform to 'AnyObject'}}
354354
z = e
355355
z = f

test/Constraints/protocols.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ f0(f)
4141
f0(b)
4242
f1(i)
4343

44-
f1(f) // expected-error{{argument type 'Float' does not conform to expected type 'Barable & Fooable'}}
45-
f1(b) // expected-error{{argument type 'Barable' does not conform to expected type 'Barable & Fooable'}}
44+
f1(f) // expected-error{{argument type 'Float' does not conform to expected type 'Fooable'}}
45+
f1(b) // expected-error{{argument type 'Barable' does not conform to expected type 'Fooable'}}
4646

4747
//===----------------------------------------------------------------------===//
4848
// Subtyping

test/TypeCoercion/protocols.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ func testPrintableCoercion(_ ip1: IsPrintable1,
4343
inp2: IsNotPrintable2,
4444
op: OtherPrintable) {
4545
var p : MyPrintable = ip1 // okay
46+
let _: MyPrintable & Titled = Book(title: "")
47+
// expected-error@-1 {{value of type 'Book' does not conform to specified type 'MyPrintable'}}
4648
p = ip1 // okay
4749
p = ip2 // okay
4850
p = inp1 // expected-error{{value of type 'IsNotPrintable1' does not conform to 'MyPrintable' in assignment}}
51+
let _: MyPrintable = inp1
52+
// expected-error@-1 {{value of type 'IsNotPrintable1' does not conform to specified type 'MyPrintable'}}
4953
p = inp2 // expected-error{{value of type 'IsNotPrintable2' does not conform to 'MyPrintable' in assignment}}
5054
p = op // expected-error{{value of type 'OtherPrintable' does not conform to 'MyPrintable' in assignment}}
5155
_ = p

test/type/protocol_composition.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func testConversion() {
111111

112112
// Conversions among existential types.
113113
var x2 : protocol<SuperREPLPrintable, FooProtocol> // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{12-53=SuperREPLPrintable & FooProtocol}}
114-
x2 = x // expected-error{{value of type 'FooProtocol & REPLPrintable' does not conform to 'FooProtocol & SuperREPLPrintable' in assignment}}
114+
x2 = x // expected-error{{value of type 'FooProtocol & REPLPrintable' does not conform to 'SuperREPLPrintable' in assignment}}
115115
x = x2
116116

117117
// Subtyping

test/type/subclass_composition.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ func basicSubtyping(
9797
anyObject: AnyObject) {
9898

9999
// Errors
100-
let _: Base & P2 = base // expected-error {{value of type 'Base<Int>' does not conform to specified type 'Base & P2'}}
101-
let _: Base<Int> & P2 = base // expected-error {{value of type 'Base<Int>' does not conform to specified type 'Base<Int> & P2'}}
100+
let _: Base & P2 = base // expected-error {{value of type 'Base<Int>' does not conform to specified type 'P2'}}
101+
let _: Base<Int> & P2 = base // expected-error {{value of type 'Base<Int>' does not conform to specified type 'P2'}}
102102
let _: P3 = baseAndP1 // expected-error {{value of type 'Base<Int> & P1' does not conform to specified type 'P3'}}
103103
let _: P3 = baseAndP2 // expected-error {{value of type 'Base<Int> & P2' does not conform to specified type 'P3'}}
104104
let _: Derived = baseAndP1 // expected-error {{cannot convert value of type 'Base<Int> & P1' to specified type 'Derived'}}

0 commit comments

Comments
 (0)