Skip to content

Commit 811fc06

Browse files
authored
Merge pull request swiftlang#34467 from xedin/protocol-conformance-error-as-note
[Diagnostics] Split "only concrete types conform to protocols" into a separate note
2 parents 9269c5c + f24e5db commit 811fc06

16 files changed

+35
-26
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,9 +1842,11 @@ ERROR(use_of_equal_instead_of_equality,none,
18421842
"use of '=' in a boolean context, did you mean '=='?", ())
18431843
ERROR(type_cannot_conform, none,
18441844
"%select{type %1|protocol %1 as a type}0 cannot conform to "
1845-
"%select{%3|the protocol itself}2; "
1846-
"only concrete types such as structs, enums and classes can conform to protocols",
1845+
"%select{%3|the protocol itself}2",
18471846
(bool, Type, bool, Type))
1847+
NOTE(only_concrete_types_conform_to_protocols,none,
1848+
"only concrete types such as structs, enums and classes can conform to protocols",
1849+
())
18481850
NOTE(required_by_opaque_return,none,
18491851
"required by opaque return type of %0 %1", (DescriptiveDeclKind, DeclName))
18501852
NOTE(required_by_decl,none,

lib/Sema/CSDiagnostics.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,8 @@ bool MissingConformanceFailure::diagnoseTypeCannotConform(
516516
nonConformingType->isEqual(protocolType),
517517
protocolType);
518518

519+
emitDiagnostic(diag::only_concrete_types_conform_to_protocols);
520+
519521
if (auto *OTD = dyn_cast<OpaqueTypeDecl>(AffectedDecl)) {
520522
auto *namingDecl = OTD->getNamingDecl();
521523
if (auto *repr = namingDecl->getOpaqueResultTypeRepr()) {
@@ -2171,6 +2173,7 @@ bool ContextualFailure::diagnoseAsError() {
21712173
emitDiagnostic(diag::type_cannot_conform,
21722174
/*isExistentialType=*/true, fromType,
21732175
fromType->isEqual(toType), toType);
2176+
emitDiagnostic(diag::only_concrete_types_conform_to_protocols);
21742177
return true;
21752178
}
21762179

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4735,6 +4735,8 @@ void swift::diagnoseConformanceFailure(Type T,
47354735
diags.diagnose(ComplainLoc, diag::type_cannot_conform, true,
47364736
T, T->isEqual(Proto->getDeclaredInterfaceType()),
47374737
Proto->getDeclaredInterfaceType());
4738+
diags.diagnose(ComplainLoc,
4739+
diag::only_concrete_types_conform_to_protocols);
47384740
return;
47394741
}
47404742

test/Constraints/diagnostics.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ f0(i, i, // expected-error@:7 {{cannot convert value of type 'Int' to expected a
5151

5252

5353
// Cannot conform to protocols.
54-
f5(f4) // expected-error {{type '(Int) -> Int' cannot conform to 'P2'; only concrete types such as structs, enums and classes can conform to protocols}}
55-
f5((1, "hello")) // expected-error {{type '(Int, String)' cannot conform to 'P2'; only concrete types such as structs, enums and classes can conform to protocols}}
56-
f5(Int.self) // expected-error {{type 'Int.Type' cannot conform to 'P2'; only concrete types such as structs, enums and classes can conform to protocols}}
54+
f5(f4) // expected-error {{type '(Int) -> Int' cannot conform to 'P2'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
55+
f5((1, "hello")) // expected-error {{type '(Int, String)' cannot conform to 'P2'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
56+
f5(Int.self) // expected-error {{type 'Int.Type' cannot conform to 'P2'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
5757

5858
// Tuple element not convertible.
5959
f0(i,
@@ -104,7 +104,7 @@ func f8<T:P2>(_ n: T, _ f: @escaping (T) -> T) {} // expected-note {{where 'T'
104104
f8(3, f4) // expected-error {{global function 'f8' requires that 'Int' conform to 'P2'}}
105105
typealias Tup = (Int, Double)
106106
func f9(_ x: Tup) -> Tup { return x }
107-
f8((1,2.0), f9) // expected-error {{type 'Tup' (aka '(Int, Double)') cannot conform to 'P2'; only concrete types such as structs, enums and classes can conform to protocols}}
107+
f8((1,2.0), f9) // expected-error {{type 'Tup' (aka '(Int, Double)') cannot conform to 'P2'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
108108

109109
// <rdar://problem/19658691> QoI: Incorrect diagnostic for calling nonexistent members on literals
110110
1.doesntExist(0) // expected-error {{value of type 'Int' has no member 'doesntExist'}}

test/Constraints/generics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func r22459135() {
188188

189189
// <rdar://problem/19710848> QoI: Friendlier error message for "[] as Set"
190190
// <rdar://problem/22326930> QoI: "argument for generic parameter 'Element' could not be inferred" lacks context
191-
_ = [] as Set // expected-error {{protocol 'Any' as a type cannot conform to 'Hashable'; only concrete types such as structs, enums and classes can conform to protocols}}
191+
_ = [] as Set // expected-error {{protocol 'Any' as a type cannot conform to 'Hashable'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
192192
// expected-note@-1 {{required by generic struct 'Set' where 'Element' = 'Any'}}
193193

194194

test/Constraints/rdar68155466.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ func data() -> [A] {
2525
}
2626

2727
_ = Loop(data(), id: \.uniqueID) { $0 } // expected-error {{key path cannot refer to instance method 'uniqueID()'}}
28-
// expected-error@-1 {{type '() -> Int' cannot conform to 'Hashable'; only concrete types such as structs, enums and classes can conform to protocols}}
28+
// expected-error@-1 {{type '() -> Int' cannot conform to 'Hashable'}} expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}}

test/Constraints/result_builder_diags.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ struct Label<L> : P where L : P { // expected-note 2 {{'L' declared as parameter
195195
}
196196

197197
func test_51167632() -> some P {
198-
AnyP(G { // expected-error {{type 'Label<_>.Type' cannot conform to 'P'; only concrete types such as structs, enums and classes can conform to protocols}}
198+
AnyP(G { // expected-error {{type 'Label<_>.Type' cannot conform to 'P'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
199199
Text("hello")
200200
Label // expected-error {{generic parameter 'L' could not be inferred}}
201201
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{10-10=<<#L: P#>>}}

test/Generics/conditional_conformances_literals.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ func combined() {
128128

129129
// Needs self conforming protocols:
130130
let _: Conforms = [[0: [1 : [works]] as Conforms]]
131-
// expected-error@-1 {{protocol 'Conforms' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
131+
// expected-error@-1 {{protocol 'Conforms' as a type cannot conform to the protocol itself}} expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}}
132132

133133
let _: Conforms = [[0: [1 : [fails]] as Conforms]]
134134
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
135-
// expected-error@-2 {{protocol 'Conforms' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
135+
// expected-error@-2 {{protocol 'Conforms' as a type cannot conform to the protocol itself}} expected-note@-2 {{only concrete types such as structs, enums and classes can conform to protocols}}
136136
}

test/Generics/existential_restrictions.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func fAOE(_ t: AnyObject) { }
2323
func fT<T>(_ t: T) { }
2424

2525
func testPassExistential(_ p: P, op: OP, opp: OP & P, cp: CP, sp: SP, any: Any, ao: AnyObject) {
26-
fP(p) // expected-error{{protocol 'P' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
26+
fP(p) // expected-error{{protocol 'P' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
2727
fAO(p) // expected-error{{global function 'fAO' requires that 'P' be a class type}}
2828
fAOE(p) // expected-error{{argument type 'P' expected to be an instance of a class or class-constrained type}}
2929
fT(p)
@@ -37,8 +37,8 @@ func testPassExistential(_ p: P, op: OP, opp: OP & P, cp: CP, sp: SP, any: Any,
3737
fAOE(cp)
3838
fT(cp)
3939

40-
fP(opp) // expected-error{{protocol 'OP & P' as a type cannot conform to 'P'; only concrete types such as structs, enums and classes can conform to protocols}}
41-
fOP(opp) // expected-error{{protocol 'OP & P' as a type cannot conform to 'OP'; only concrete types such as structs, enums and classes can conform to protocols}}
40+
fP(opp) // expected-error{{protocol 'OP & P' as a type cannot conform to 'P'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
41+
fOP(opp) // expected-error{{protocol 'OP & P' as a type cannot conform to 'OP'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
4242
fAO(opp) // expected-error{{global function 'fAO' requires that 'OP & P' be a class type}}
4343
fAOE(opp)
4444
fT(opp)
@@ -64,9 +64,9 @@ class GAO<T : AnyObject> {} // expected-note 2{{requirement specified as 'T' : '
6464
func blackHole(_ t: Any) {}
6565

6666
func testBindExistential() {
67-
blackHole(GP<P>()) // expected-error{{protocol 'P' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
67+
blackHole(GP<P>()) // expected-error{{protocol 'P' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
6868
blackHole(GOP<OP>())
69-
blackHole(GCP<CP>()) // expected-error{{protocol 'CP' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
69+
blackHole(GCP<CP>()) // expected-error{{protocol 'CP' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
7070
blackHole(GAO<P>()) // expected-error{{'GAO' requires that 'P' be a class type}}
7171
blackHole(GAO<OP>())
7272
blackHole(GAO<CP>()) // expected-error{{'GAO' requires that 'CP' be a class type}}
@@ -92,5 +92,5 @@ func foo() {
9292
// generic no overloads error path. The error should actually talk
9393
// about the return type, and this can happen in other contexts as well;
9494
// <rdar://problem/21900971> tracks improving QoI here.
95-
allMine.takeAll() // expected-error{{protocol 'Mine' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
95+
allMine.takeAll() // expected-error{{protocol 'Mine' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
9696
}

test/Parse/confusables.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ if (true ꝸꝸꝸ false) {} // expected-note {{identifier 'ꝸꝸꝸ' contains
1717

1818
// expected-error @+3 {{invalid character in source file}}
1919
// expected-error @+2 {{expected ',' separator}}
20-
// expected-error @+1 {{type '(Int, Int)' cannot conform to 'BinaryInteger'; only concrete types such as structs, enums and classes can conform to protocols}}
20+
// expected-error @+1 {{type '(Int, Int)' cannot conform to 'BinaryInteger'}}
2121
if (55) == 0 {} // expected-note {{unicode character '‒' (Figure Dash) looks similar to '-' (Hyphen Minus); did you mean to use '-' (Hyphen Minus)?}} {{7-10=-}}
2222
// expected-note @-1 {{operator function '=='}}
23+
// expected-note @-2 {{only concrete types such as structs, enums and classes can conform to protocols}}
2324

2425
// FIXME(rdar://61028087): The above note should read "required by referencing operator function '==' on 'BinaryInteger' where 'Self' = '(Int, Int)'".
2526

0 commit comments

Comments
 (0)