Skip to content

Commit f2fb1e9

Browse files
authored
[Sema] Record invalid protocol witnesses to avoid re-diagnosis. (#6698)
This is a /little/ risky because previously a recorded witness would only be empty if the requirement was optional, but it's a relatively non-intrusive way to improve diagnostics. The conformance is still marked invalid, which is the important part. Groundwork for rdar://problem/28543037.
1 parent 549e00c commit f2fb1e9

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,9 @@ namespace {
17091709
/// Record that the given optional requirement has no witness.
17101710
void recordOptionalWitness(ValueDecl *requirement);
17111711

1712+
/// Record that the given requirement has no valid witness.
1713+
void recordInvalidWitness(ValueDecl *requirement);
1714+
17121715
/// Record a type witness.
17131716
///
17141717
/// \param assocType The associated type whose witness is being recorded.
@@ -2186,6 +2189,20 @@ void ConformanceChecker::recordOptionalWitness(ValueDecl *requirement) {
21862189
Conformance->setWitness(requirement, Witness());
21872190
}
21882191

2192+
void ConformanceChecker::recordInvalidWitness(ValueDecl *requirement) {
2193+
assert(Conformance->isInvalid());
2194+
2195+
// If we already recorded this witness, don't do so again.
2196+
if (Conformance->hasWitness(requirement)) {
2197+
assert(!Conformance->getWitness(requirement, nullptr).getDecl() &&
2198+
"Already have a non-optional witness?");
2199+
return;
2200+
}
2201+
2202+
// Record that there is no witness.
2203+
Conformance->setWitness(requirement, Witness());
2204+
}
2205+
21892206
void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType,
21902207
Type type,
21912208
TypeDecl *typeDecl,
@@ -4019,6 +4036,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
40194036

40204037
case ResolveWitnessResult::ExplicitFailed:
40214038
Conformance->setInvalid();
4039+
recordInvalidWitness(requirement);
40224040
return;
40234041

40244042
case ResolveWitnessResult::Missing:
@@ -4033,6 +4051,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
40334051

40344052
case ResolveWitnessResult::ExplicitFailed:
40354053
Conformance->setInvalid();
4054+
recordInvalidWitness(requirement);
40364055
return;
40374056

40384057
case ResolveWitnessResult::Missing:
@@ -4047,6 +4066,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
40474066

40484067
case ResolveWitnessResult::ExplicitFailed:
40494068
Conformance->setInvalid();
4069+
recordInvalidWitness(requirement);
40504070
return;
40514071

40524072
case ResolveWitnessResult::Missing:

test/ClangImporter/objc_parse.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,14 @@ class ProtocolAdopter2 : FooProto {
356356
set { /* do nothing! */ }
357357
}
358358
}
359-
class ProtocolAdopterBad1 : FooProto { // expected-error 2{{type 'ProtocolAdopterBad1' does not conform to protocol 'FooProto'}}
360-
@objc var bar: Int = 0 // expected-note 2{{candidate has non-matching type 'Int'}}
359+
class ProtocolAdopterBad1 : FooProto { // expected-error {{type 'ProtocolAdopterBad1' does not conform to protocol 'FooProto'}}
360+
@objc var bar: Int = 0 // expected-note {{candidate has non-matching type 'Int'}}
361361
}
362-
class ProtocolAdopterBad2 : FooProto { // expected-error 2{{type 'ProtocolAdopterBad2' does not conform to protocol 'FooProto'}}
363-
let bar: CInt = 0 // expected-note 2{{candidate is not settable, but protocol requires it}}
362+
class ProtocolAdopterBad2 : FooProto { // expected-error {{type 'ProtocolAdopterBad2' does not conform to protocol 'FooProto'}}
363+
let bar: CInt = 0 // expected-note {{candidate is not settable, but protocol requires it}}
364364
}
365-
class ProtocolAdopterBad3 : FooProto { // expected-error 2{{type 'ProtocolAdopterBad3' does not conform to protocol 'FooProto'}}
366-
var bar: CInt { // expected-note 2{{candidate is not settable, but protocol requires it}}
365+
class ProtocolAdopterBad3 : FooProto { // expected-error {{type 'ProtocolAdopterBad3' does not conform to protocol 'FooProto'}}
366+
var bar: CInt { // expected-note {{candidate is not settable, but protocol requires it}}
367367
return 42
368368
}
369369
}

0 commit comments

Comments
 (0)