Skip to content

Commit 811fc06

Browse files
authored
Merge pull request #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

+4-2
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

+3
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

+2
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

+4-4
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

+1-1
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

+1-1
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

+1-1
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

+2-2
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

+6-6
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

+2-1
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

test/decl/protocol/conforms/error_self_conformance.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ func testSimple(error: Error) {
1111

1212
protocol ErrorRefinement : Error {}
1313
func testErrorRefinment(error: ErrorRefinement) {
14-
wantsError(error) // expected-error {{protocol 'ErrorRefinement' as a type cannot conform to 'Error'; only concrete types such as structs, enums and classes can conform to protocols}}
14+
wantsError(error) // expected-error {{protocol 'ErrorRefinement' as a type cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
1515
}
1616

1717
protocol OtherProtocol {}
1818
func testErrorComposition(error: Error & OtherProtocol) {
19-
wantsError(error) // expected-error {{protocol 'Error & OtherProtocol' as a type cannot conform to 'Error'; only concrete types such as structs, enums and classes can conform to protocols}}
19+
wantsError(error) // expected-error {{protocol 'Error & OtherProtocol' as a type cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
2020
}
2121

2222
class C {}
2323
func testErrorCompositionWithClass(error: Error & C) {
24-
wantsError(error) // expected-error {{protocol 'C & Error' as a type cannot conform to 'Error'; only concrete types such as structs, enums and classes can conform to protocols}}
24+
wantsError(error) // expected-error {{protocol 'C & Error' as a type cannot conform to 'Error'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
2525
}

test/stmt/foreach.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func testOptionalSequence() {
177177

178178
// Crash with (invalid) for each over an existential
179179
func testExistentialSequence(s: Sequence) { // expected-error {{protocol 'Sequence' can only be used as a generic constraint because it has Self or associated type requirements}}
180-
for x in s { // expected-error {{protocol 'Sequence' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
180+
for x in s { // expected-error {{protocol 'Sequence' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
181181
_ = x
182182
}
183183
}

test/type/opaque.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ protocol P_51641323 {
383383
func rdar_51641323() {
384384
struct Foo: P_51641323 {
385385
var foo: some P_51641323 { // expected-note {{required by opaque return type of property 'foo'}}
386-
{} // expected-error {{type '() -> ()' cannot conform to 'P_51641323'; only concrete types such as structs, enums and classes can conform to protocols}}
386+
{} // expected-error {{type '() -> ()' cannot conform to 'P_51641323'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
387387
}
388388
}
389389
}

test/type/subclass_composition.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ func conformsTo<T1 : P2, T2 : Base<Int> & P2>(
413413
// expected-error@-1 {{global function 'conformsToAnyObject' requires that 'P1' be a class type}}
414414

415415
conformsToP1(p1)
416-
// expected-error@-1 {{protocol 'P1' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
416+
// expected-error@-1 {{protocol 'P1' as a type cannot conform to the protocol itself}}
417+
// expected-note@-2 {{only concrete types such as structs, enums and classes can conform to protocols}}
417418

418419
// FIXME: Following diagnostics are not great because when
419420
// `conformsTo*` methods are re-typechecked, they loose information

validation-test/compiler_crashers_2_fixed/0196-rdar48937223.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ func fn<T, U: P>(_ arg1: T, arg2: (T) -> U) {}
66
// expected-note@-1 {{required by global function 'fn(_:arg2:)' where 'U' = '()'}}
77

88
func test(str: String) {
9-
fn(str) { arg in // expected-error {{type '()' cannot conform to 'P'; only concrete types such as structs, enums and classes can conform to protocols}}
9+
fn(str) { arg in // expected-error {{type '()' cannot conform to 'P'}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
1010
<#FOO#> // expected-error {{editor placeholder in source file}}
1111
}
1212
}

validation-test/compiler_crashers_fixed/00017-llvm-foldingset-llvm-attributesetnode-nodeequals.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ extension Bool : BooleanProtocol {
2020
func f<T : BooleanProtocol>(_ b: T) {}
2121
// expected-note@-1 {{required by global function 'f' where 'T' = 'BooleanProtocol'}}
2222

23-
f(true as BooleanProtocol) // expected-error {{protocol 'BooleanProtocol' as a type cannot conform to the protocol itself; only concrete types such as structs, enums and classes can conform to protocols}}
23+
f(true as BooleanProtocol) // expected-error {{protocol 'BooleanProtocol' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}

0 commit comments

Comments
 (0)