Skip to content

Commit d5c561b

Browse files
committed
[ConstraintSystem] Move missing contextual protocol detection to matchExistentialTypes
1 parent 577e629 commit d5c561b

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
@@ -2303,8 +2303,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
23032303

23042304
// When complaining about conversion to a protocol type, complain about
23052305
// conformance instead of "conversion".
2306-
if (contextualType->is<ProtocolType>() ||
2307-
contextualType->is<ProtocolCompositionType>()) {
2306+
if (contextualType->isExistentialType()) {
23082307
MissingContextualConformanceFailure failure(
23092308
expr, CS, CTP, exprType, contextualType,
23102309
CS.getConstraintLocator(expr, ConstraintLocator::ContextualType));

lib/Sema/CSDiagnostics.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2903,10 +2903,28 @@ bool MissingContextualConformanceFailure::diagnoseAsError() {
29032903
assert(Context != CTP_Unused);
29042904
diagnostic = getDiagnosticFor(Context);
29052905
break;
2906+
2907+
default:
2908+
break;
29062909
}
29072910
}
29082911

2909-
emitDiagnostic(anchor->getLoc(), *diagnostic, getFromType(), getToType());
2912+
if (!diagnostic)
2913+
return false;
2914+
2915+
auto srcType = getFromType();
2916+
auto dstType = getToType();
2917+
2918+
emitDiagnostic(anchor->getLoc(), *diagnostic, srcType, dstType);
2919+
2920+
if (isa<InOutExpr>(anchor))
2921+
return true;
2922+
2923+
if (srcType->isAny() && dstType->isAnyObject()) {
2924+
emitDiagnostic(anchor->getLoc(), diag::any_as_anyobject_fixit)
2925+
.fixItInsertAfter(anchor->getEndLoc(), " as AnyObject");
2926+
}
2927+
29102928
return true;
29112929
}
29122930

lib/Sema/CSSimplify.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,8 +1762,28 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
17621762
case SolutionKind::Unsolved:
17631763
break;
17641764

1765-
case SolutionKind::Error:
1766-
return getTypeMatchFailure(locator);
1765+
case SolutionKind::Error: {
1766+
if (!shouldAttemptFixes())
1767+
return getTypeMatchFailure(locator);
1768+
1769+
if (auto last = locator.last()) {
1770+
// TODO(diagnostics): Diagnosing missing conformances
1771+
// associated with arguments requires having general
1772+
// conversion failures implemented first, otherwise
1773+
// we would be misdiagnosing ambiguous cases associated
1774+
// with overloaded declarations.
1775+
if (last->getKind() == ConstraintLocator::ApplyArgToParam)
1776+
return getTypeMatchFailure(locator);
1777+
}
1778+
1779+
auto *fix = MissingConformance::forContextual(
1780+
*this, type1, proto, getConstraintLocator(locator));
1781+
1782+
if (recordFix(fix))
1783+
return getTypeMatchFailure(locator);
1784+
1785+
break;
1786+
}
17671787
}
17681788
}
17691789

@@ -2040,12 +2060,8 @@ bool ConstraintSystem::repairFailures(
20402060
return false;
20412061
};
20422062

2043-
auto repairByAddingConformance = [&](Type lhs, Type rhs) -> bool {
2044-
if (lhs->isTypeVariableOrMember())
2045-
return false;
2046-
2047-
if (rhs->isAny() ||
2048-
!(rhs->is<ProtocolType>() || rhs->is<ProtocolCompositionType>()))
2063+
auto repairByAnyToAnyObjectCast = [&](Type lhs, Type rhs) -> bool {
2064+
if (!(lhs->isAny() && rhs->isAnyObject()))
20492065
return false;
20502066

20512067
conversionsOrFixes.push_back(MissingConformance::forContextual(
@@ -2072,14 +2088,14 @@ bool ConstraintSystem::repairFailures(
20722088
if (repairByInsertingExplicitCall(lhs, rhs))
20732089
return true;
20742090

2075-
if (repairByAddingConformance(lhs, rhs))
2076-
return true;
2077-
20782091
if (isa<InOutExpr>(AE->getSrc())) {
20792092
conversionsOrFixes.push_back(
20802093
RemoveAddressOf::create(*this, getConstraintLocator(locator)));
20812094
return true;
20822095
}
2096+
2097+
if (repairByAnyToAnyObjectCast(lhs, rhs))
2098+
return true;
20832099
}
20842100

20852101
return false;
@@ -2166,7 +2182,7 @@ bool ConstraintSystem::repairFailures(
21662182
if (repairByInsertingExplicitCall(lhs, rhs))
21672183
return true;
21682184

2169-
if (repairByAddingConformance(lhs, rhs))
2185+
if (repairByAnyToAnyObjectCast(lhs, rhs))
21702186
return true;
21712187

21722188
// 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)