Skip to content

Commit 17643a3

Browse files
committed
[ConstraintSystem] Move missing contextual protocol detection to matchExistentialTypes
1 parent ada6ab5 commit 17643a3

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

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

lib/Sema/CSDiagnostics.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2828,10 +2828,28 @@ bool MissingContextualConformanceFailure::diagnoseAsError() {
28282828
assert(Context != CTP_Unused);
28292829
diagnostic = getDiagnosticFor(Context);
28302830
break;
2831+
2832+
default:
2833+
break;
28312834
}
28322835
}
28332836

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

lib/Sema/CSSimplify.cpp

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

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

@@ -2039,12 +2059,8 @@ bool ConstraintSystem::repairFailures(
20392059
return false;
20402060
};
20412061

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

20502066
conversionsOrFixes.push_back(MissingConformance::forContextual(
@@ -2071,14 +2087,14 @@ bool ConstraintSystem::repairFailures(
20712087
if (repairByInsertingExplicitCall(lhs, rhs))
20722088
return true;
20732089

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

20842100
return false;
@@ -2165,7 +2181,7 @@ bool ConstraintSystem::repairFailures(
21652181
if (repairByInsertingExplicitCall(lhs, rhs))
21662182
return true;
21672183

2168-
if (repairByAddingConformance(lhs, rhs))
2184+
if (repairByAnyToAnyObjectCast(lhs, rhs))
21692185
return true;
21702186

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