Skip to content

Commit 29044e5

Browse files
authored
Merge pull request #27176 from hborla/type-cannot-conform-diag
[Diagnostics] Generalize the "protocol type cannot conform" error to work for all types that cannot conform to protocols.
2 parents f73c4c4 + 85e6f73 commit 29044e5

18 files changed

+134
-45
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,10 +1665,19 @@ ERROR(cannot_use_nil_with_this_type,none,
16651665
ERROR(use_of_equal_instead_of_equality,none,
16661666
"use of '=' in a boolean context, did you mean '=='?", ())
16671667

1668+
ERROR(type_cannot_conform, none,
1669+
"%select{|value of protocol }0type %1 cannot conform to %2; "
1670+
"only struct/enum/class types can conform to protocols",
1671+
(bool, Type, Type))
1672+
NOTE(required_by_opaque_return,none,
1673+
"required by opaque return type of %0 %1", (DescriptiveDeclKind, DeclName))
1674+
NOTE(required_by_decl,none,
1675+
"required by %0 %1 where %2 = %3",
1676+
(DescriptiveDeclKind, DeclName, Type, Type))
1677+
NOTE(required_by_decl_ref,none,
1678+
"required by referencing %0 %1 on %2 where %3 = %4",
1679+
(DescriptiveDeclKind, DeclName, Type, Type, Type))
16681680

1669-
ERROR(protocol_does_not_conform_objc,none,
1670-
"protocol type %0 cannot conform to %1 because only concrete "
1671-
"types can conform to protocols", (Type, Type))
16721681
ERROR(protocol_does_not_conform_static,none,
16731682
"%0 cannot be used as a type conforming to protocol %1 because %1 "
16741683
"has static requirements",

lib/Sema/CSDiagnostics.cpp

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -593,16 +593,18 @@ bool MissingConformanceFailure::diagnoseAsError() {
593593
}
594594
}
595595

596-
if (nonConformingType->isExistentialType()) {
597-
auto diagnostic = diag::protocol_does_not_conform_objc;
598-
if (nonConformingType->isObjCExistentialType())
599-
diagnostic = diag::protocol_does_not_conform_static;
600-
601-
emitDiagnostic(anchor->getLoc(), diagnostic, nonConformingType,
602-
protocolType);
596+
if (nonConformingType->isObjCExistentialType()) {
597+
emitDiagnostic(anchor->getLoc(), diag::protocol_does_not_conform_static,
598+
nonConformingType, protocolType);
603599
return true;
604600
}
605601

602+
if (diagnoseTypeCannotConform((atParameterPos ?
603+
getArgumentAt(Apply, *atParameterPos) : anchor),
604+
nonConformingType, protocolType)) {
605+
return true;
606+
}
607+
606608
if (atParameterPos) {
607609
// Requirement comes from one of the parameter types,
608610
// let's try to point diagnostic to the argument expression.
@@ -618,6 +620,58 @@ bool MissingConformanceFailure::diagnoseAsError() {
618620
return RequirementFailure::diagnoseAsError();
619621
}
620622

623+
bool MissingConformanceFailure::diagnoseTypeCannotConform(Expr *anchor,
624+
Type nonConformingType, Type protocolType) const {
625+
if (!(nonConformingType->is<AnyFunctionType>() ||
626+
nonConformingType->is<TupleType>() ||
627+
nonConformingType->isExistentialType() ||
628+
nonConformingType->is<AnyMetatypeType>())) {
629+
return false;
630+
}
631+
632+
emitDiagnostic(anchor->getLoc(), diag::type_cannot_conform,
633+
nonConformingType->isExistentialType(), nonConformingType,
634+
protocolType);
635+
636+
if (auto *OTD = dyn_cast<OpaqueTypeDecl>(AffectedDecl)) {
637+
auto *namingDecl = OTD->getNamingDecl();
638+
if (auto *repr = namingDecl->getOpaqueResultTypeRepr()) {
639+
emitDiagnostic(repr->getLoc(), diag::required_by_opaque_return,
640+
namingDecl->getDescriptiveKind(), namingDecl->getFullName())
641+
.highlight(repr->getSourceRange());
642+
}
643+
return true;
644+
}
645+
646+
auto &req = getRequirement();
647+
auto *reqDC = getRequirementDC();
648+
auto *genericCtx = getGenericContext();
649+
auto noteLocation = reqDC->getAsDecl()->getLoc();
650+
651+
if (!noteLocation.isValid())
652+
noteLocation = anchor->getLoc();
653+
654+
if (isConditional()) {
655+
emitDiagnostic(noteLocation, diag::requirement_implied_by_conditional_conformance,
656+
resolveType(Conformance->getType()),
657+
Conformance->getProtocol()->getDeclaredInterfaceType());
658+
} else if (genericCtx != reqDC && (genericCtx->isChildContextOf(reqDC) ||
659+
isStaticOrInstanceMember(AffectedDecl))) {
660+
emitDiagnostic(noteLocation, diag::required_by_decl_ref,
661+
AffectedDecl->getDescriptiveKind(),
662+
AffectedDecl->getFullName(),
663+
reqDC->getSelfNominalTypeDecl()->getDeclaredType(),
664+
req.getFirstType(), nonConformingType);
665+
} else {
666+
emitDiagnostic(noteLocation, diag::required_by_decl,
667+
AffectedDecl->getDescriptiveKind(),
668+
AffectedDecl->getFullName(), req.getFirstType(),
669+
nonConformingType);
670+
}
671+
672+
return true;
673+
}
674+
621675
bool MissingConformanceFailure::diagnoseAsAmbiguousOperatorRef() {
622676
auto *anchor = getRawAnchor();
623677
auto *ODRE = dyn_cast<OverloadedDeclRefExpr>(anchor);

lib/Sema/CSDiagnostics.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ class RequirementFailure : public FailureDiagnostic {
290290
isa<BinaryExpr>(apply);
291291
}
292292

293+
/// Determine whether given declaration represents a static
294+
/// or instance property/method, excluding operators.
295+
static bool isStaticOrInstanceMember(const ValueDecl *decl);
296+
293297
private:
294298
/// Retrieve declaration associated with failing generic requirement.
295299
ValueDecl *getDeclRef() const;
@@ -299,10 +303,6 @@ class RequirementFailure : public FailureDiagnostic {
299303

300304
void emitRequirementNote(const Decl *anchor, Type lhs, Type rhs) const;
301305

302-
/// Determine whether given declaration represents a static
303-
/// or instance property/method, excluding operators.
304-
static bool isStaticOrInstanceMember(const ValueDecl *decl);
305-
306306
/// If this is a failure in conditional requirement, retrieve
307307
/// conformance information.
308308
ProtocolConformance *
@@ -346,6 +346,10 @@ class MissingConformanceFailure final : public RequirementFailure {
346346
DiagAsNote getDiagnosticAsNote() const override {
347347
return diag::candidate_types_conformance_requirement;
348348
}
349+
350+
private:
351+
bool diagnoseTypeCannotConform(Expr *anchor, Type nonConformingType,
352+
Type protocolType) const;
349353
};
350354

351355
/// Diagnose failures related to same-type generic requirements, e.g.

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3970,7 +3970,7 @@ static void diagnoseConformanceFailure(Type T,
39703970
TypeChecker::containsProtocol(T, Proto, DC, None)) {
39713971

39723972
if (!T->isObjCExistentialType()) {
3973-
diags.diagnose(ComplainLoc, diag::protocol_does_not_conform_objc,
3973+
diags.diagnose(ComplainLoc, diag::type_cannot_conform, true,
39743974
T, Proto->getDeclaredType());
39753975
return;
39763976
}

test/Constraints/diagnostics.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ func f3(_: @escaping (_: @escaping (Int) -> Float) -> Int) {}
2828
func f4(_ x: Int) -> Int { }
2929

3030
func f5<T : P2>(_ : T) { }
31+
// expected-note@-1 {{required by global function 'f5' where 'T' = '(Int) -> Int'}}
32+
// expected-note@-2 {{required by global function 'f5' where 'T' = '(Int, String)'}}
33+
// expected-note@-3 {{required by global function 'f5' where 'T' = 'Int.Type'}}
3134

3235
func f6<T : P, U : P>(_ t: T, _ u: U) where T.SomeType == U.SomeType {}
3336

@@ -46,8 +49,10 @@ f0(i, i,
4649
i) // expected-error{{extra argument in call}}
4750

4851

49-
// Position mismatch
50-
f5(f4) // expected-error {{argument type '(Int) -> Int' does not conform to expected type 'P2'}}
52+
// Cannot conform to protocols.
53+
f5(f4) // expected-error {{type '(Int) -> Int' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
54+
f5((1, "hello")) // expected-error {{type '(Int, String)' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
55+
f5(Int.self) // expected-error {{type 'Int.Type' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
5156

5257
// Tuple element not convertible.
5358
f0(i,
@@ -94,10 +99,11 @@ func f7() -> (c: Int, v: A) {
9499
}
95100

96101
func f8<T:P2>(_ n: T, _ f: @escaping (T) -> T) {}
102+
// expected-note@-1 {{required by global function 'f8' where 'T' = 'Tup' (aka '(Int, Double)')}}
97103
f8(3, f4) // expected-error {{argument type 'Int' does not conform to expected type 'P2'}}
98104
typealias Tup = (Int, Double)
99105
func f9(_ x: Tup) -> Tup { return x }
100-
f8((1,2.0), f9) // expected-error {{argument type 'Tup' (aka '(Int, Double)') does not conform to expected type 'P2'}}
106+
f8((1,2.0), f9) // expected-error {{type 'Tup' (aka '(Int, Double)') cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
101107

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

test/Constraints/function_builder_diags.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ struct TupleP<U> : P {
144144

145145
@_functionBuilder
146146
struct Builder {
147-
static func buildBlock<S0, S1>(_ stmt1: S0, _ stmt2: S1) // expected-note {{where 'S1' = 'Label<Any>.Type'}}
147+
static func buildBlock<S0, S1>(_ stmt1: S0, _ stmt2: S1) // expected-note {{required by static method 'buildBlock' where 'S1' = 'Label<Any>.Type'}}
148148
-> TupleP<(S0, S1)> where S0: P, S1: P {
149149
return TupleP((stmt1, stmt2))
150150
}
@@ -166,7 +166,7 @@ struct Label<L> : P where L : P { // expected-note {{'L' declared as parameter t
166166
}
167167

168168
func test_51167632() -> some P {
169-
AnyP(G { // expected-error {{static method 'buildBlock' requires that 'Label<Any>.Type' conform to 'P'}}
169+
AnyP(G { // expected-error {{type 'Label<Any>.Type' cannot conform to 'P'; only struct/enum/class types can conform to protocols}}
170170
Text("hello")
171171
Label // expected-error {{generic parameter 'L' could not be inferred}}
172172
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{10-10=<<#L: P#>>}}

test/Constraints/generics.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ 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 type 'Any' cannot conform to 'Hashable' because only concrete types can conform to protocols}}
191+
_ = [] as Set // expected-error {{value of protocol type 'Any' cannot conform to 'Hashable'; only struct/enum/class types can conform to protocols}}
192+
// expected-note@-1 {{required by generic struct 'Set' where 'Element' = 'Any'}}
192193

193194

194195
//<rdar://problem/22509125> QoI: Error when unable to infer generic archetype lacks greatness

test/Constraints/operator.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ func rdar46459603() {
220220
// expected-error@-1 {{binary operator '==' cannot be applied to operands of type 'Dictionary<String, E>.Values' and '[E]'}}
221221
// expected-note@-2 {{expected an argument list of type '(Self, Self)'}}
222222
_ = [arr.values] == [[e]]
223-
// expected-error@-1 {{protocol type 'Any' cannot conform to 'Equatable' because only concrete types can conform to protocols}}
223+
// expected-error@-1 {{value of protocol type 'Any' cannot conform to 'Equatable'; only struct/enum/class types can conform to protocols}}
224+
// expected-note@-2 {{requirement from conditional conformance of '[Any]' to 'Equatable'}}
224225
}
225226

226227
// SR-10843

test/Generics/conditional_conformances_literals.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extension Array: Conforms where Element: Conforms {}
1616
// expected-note@-1 5 {{requirement from conditional conformance of '[Fails]' to 'Conforms'}}
1717
extension Dictionary: Conforms where Value: Conforms {}
1818
// expected-note@-1 3 {{requirement from conditional conformance of '[Int : Fails]' to 'Conforms'}}
19+
// expected-note@-2 2 {{requirement from conditional conformance of '[Int : Conforms]' to 'Conforms'}}
1920

2021
let works = Works()
2122
let fails = Fails()
@@ -127,9 +128,9 @@ func combined() {
127128

128129
// Needs self conforming protocols:
129130
let _: Conforms = [[0: [1 : [works]] as Conforms]]
130-
// expected-error@-1 {{protocol type 'Conforms' cannot conform to 'Conforms' because only concrete types can conform to protocols}}
131+
// expected-error@-1 {{value of protocol type 'Conforms' cannot conform to 'Conforms'; only struct/enum/class types can conform to protocols}}
131132

132133
let _: Conforms = [[0: [1 : [fails]] as Conforms]]
133134
// expected-error@-1 {{protocol 'Conforms' requires that 'Fails' conform to 'Conforms'}}
134-
// expected-error@-2 {{protocol type 'Conforms' cannot conform to 'Conforms' because only concrete types can conform to protocols}}
135+
// expected-error@-2 {{value of protocol type 'Conforms' cannot conform to 'Conforms'; only struct/enum/class types can conform to protocols}}
135136
}

test/Generics/existential_restrictions.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@ protocol CP : class { }
99
}
1010

1111
func fP<T : P>(_ t: T) { }
12+
// expected-note@-1 {{required by global function 'fP' where 'T' = 'P'}}
13+
// expected-note@-2 {{required by global function 'fP' where 'T' = 'OP & P'}}
1214
func fOP<T : OP>(_ t: T) { }
15+
// expected-note@-1 {{required by global function 'fOP' where 'T' = 'OP & P'}}
1316
func fOPE(_ t: OP) { }
1417
func fSP<T : SP>(_ t: T) { }
1518
func fAO<T : AnyObject>(_ t: T) { }
1619
func fAOE(_ t: AnyObject) { }
1720
func fT<T>(_ t: T) { }
1821

1922
func testPassExistential(_ p: P, op: OP, opp: OP & P, cp: CP, sp: SP, any: Any, ao: AnyObject) {
20-
fP(p) // expected-error{{protocol type 'P' cannot conform to 'P' because only concrete types can conform to protocols}}
23+
fP(p) // expected-error{{value of protocol type 'P' cannot conform to 'P'; only struct/enum/class types can conform to protocols}}
2124
fAO(p) // expected-error{{cannot invoke 'fAO' with an argument list of type '(P)'}} // expected-note{{expected an argument list of type '(T)'}}
2225
fAOE(p) // expected-error{{argument type 'P' does not conform to expected type 'AnyObject'}}
2326
fT(p)
@@ -31,8 +34,8 @@ func testPassExistential(_ p: P, op: OP, opp: OP & P, cp: CP, sp: SP, any: Any,
3134
fAOE(cp)
3235
fT(cp)
3336

34-
fP(opp) // expected-error{{protocol type 'OP & P' cannot conform to 'P' because only concrete types can conform to protocols}}
35-
fOP(opp) // expected-error{{protocol type 'OP & P' cannot conform to 'OP' because only concrete types can conform to protocols}}
37+
fP(opp) // expected-error{{value of protocol type 'OP & P' cannot conform to 'P'; only struct/enum/class types can conform to protocols}}
38+
fOP(opp) // expected-error{{value of protocol type 'OP & P' cannot conform to 'OP'; only struct/enum/class types can conform to protocols}}
3639
fAO(opp) // expected-error{{cannot invoke 'fAO' with an argument list of type '(OP & P)'}} // expected-note{{expected an argument list of type '(T)'}}
3740
fAOE(opp)
3841
fT(opp)
@@ -58,9 +61,9 @@ class GAO<T : AnyObject> {} // expected-note 2{{requirement specified as 'T' : '
5861
func blackHole(_ t: Any) {}
5962

6063
func testBindExistential() {
61-
blackHole(GP<P>()) // expected-error{{protocol type 'P' cannot conform to 'P' because only concrete types can conform to protocols}}
64+
blackHole(GP<P>()) // expected-error{{value of protocol type 'P' cannot conform to 'P'; only struct/enum/class types can conform to protocols}}
6265
blackHole(GOP<OP>())
63-
blackHole(GCP<CP>()) // expected-error{{protocol type 'CP' cannot conform to 'CP' because only concrete types can conform to protocols}}
66+
blackHole(GCP<CP>()) // expected-error{{value of protocol type 'CP' cannot conform to 'CP'; only struct/enum/class types can conform to protocols}}
6467
blackHole(GAO<P>()) // expected-error{{'GAO' requires that 'P' be a class type}}
6568
blackHole(GAO<OP>())
6669
blackHole(GAO<CP>()) // expected-error{{'GAO' requires that 'CP' be a class type}}
@@ -73,6 +76,7 @@ protocol Mine {}
7376
class M1: Mine {}
7477
class M2: Mine {}
7578
extension Collection where Iterator.Element : Mine {
79+
// expected-note@-1 {{required by referencing instance method 'takeAll()' on 'Collection'}}
7680
func takeAll() {}
7781
}
7882

@@ -85,5 +89,5 @@ func foo() {
8589
// generic no overloads error path. The error should actually talk
8690
// about the return type, and this can happen in other contexts as well;
8791
// <rdar://problem/21900971> tracks improving QoI here.
88-
allMine.takeAll() // expected-error{{protocol type 'Mine' cannot conform to 'Mine' because only concrete types can conform to protocols}}
92+
allMine.takeAll() // expected-error{{value of protocol type 'Mine' cannot conform to 'Mine'; only struct/enum/class types can conform to protocols}}
8993
}

test/Parse/confusables.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ 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 {{argument type '(Int, Int)' does not conform to expected type 'BinaryInteger'}}
20+
// expected-error @+1 {{type '(Int, Int)' cannot conform to 'BinaryInteger'; only struct/enum/class types can conform to protocols}}
2121
if (55) == 0 {} // expected-note {{unicode character '‒' looks similar to '-'; did you mean to use '-'?}} {{7-10=-}}
22+
// expected-note @-1 {{required by referencing operator function '==' on 'BinaryInteger' where 'Self' = '(Int, Int)'}}
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
// RUN: %target-typecheck-verify-swift
22

33
func wantsError<T: Error>(_: T) {}
4+
// expected-note@-1 {{required by global function 'wantsError' where 'T' = 'ErrorRefinement'}}
5+
// expected-note@-2 {{required by global function 'wantsError' where 'T' = 'Error & OtherProtocol'}}
6+
// expected-note@-3 {{required by global function 'wantsError' where 'T' = 'C & Error'}}
47

58
func testSimple(error: Error) {
69
wantsError(error)
710
}
811

912
protocol ErrorRefinement : Error {}
1013
func testErrorRefinment(error: ErrorRefinement) {
11-
wantsError(error) // expected-error {{protocol type 'ErrorRefinement' cannot conform to 'Error' because only concrete types can conform to protocols}}
14+
wantsError(error) // expected-error {{value of protocol type 'ErrorRefinement' cannot conform to 'Error'; only struct/enum/class types can conform to protocols}}
1215
}
1316

1417
protocol OtherProtocol {}
1518
func testErrorComposition(error: Error & OtherProtocol) {
16-
wantsError(error) // expected-error {{protocol type 'Error & OtherProtocol' cannot conform to 'Error' because only concrete types can conform to protocols}}
19+
wantsError(error) // expected-error {{value of protocol type 'Error & OtherProtocol' cannot conform to 'Error'; only struct/enum/class types can conform to protocols}}
1720
}
1821

1922
class C {}
2023
func testErrorCompositionWithClass(error: Error & C) {
21-
wantsError(error) // expected-error {{protocol type 'C & Error' cannot conform to 'Error' because only concrete types can conform to protocols}}
24+
wantsError(error) // expected-error {{value of protocol type 'C & Error' cannot conform to 'Error'; only struct/enum/class types can conform to protocols}}
2225
}

test/stmt/foreach.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func testOptionalSequence() {
179179

180180
// Crash with (invalid) for each over an existential
181181
func testExistentialSequence(s: Sequence) { // expected-error {{protocol 'Sequence' can only be used as a generic constraint because it has Self or associated type requirements}}
182-
for x in s { // expected-error {{protocol type 'Sequence' cannot conform to 'Sequence' because only concrete types can conform to protocols}}
182+
for x in s { // expected-error {{value of protocol type 'Sequence' cannot conform to 'Sequence'; only struct/enum/class types can conform to protocols}}
183183
_ = x
184184
}
185185
}

test/type/opaque.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,9 @@ protocol P_51641323 {
376376

377377
func rdar_51641323() {
378378
struct Foo: P_51641323 {
379-
var foo: some P_51641323 { {} }
380-
// expected-error@-1 {{return type of property 'foo' requires that '() -> ()' conform to 'P_51641323'}}
381-
// expected-note@-2 {{opaque return type declared here}}
379+
var foo: some P_51641323 { // expected-note {{required by opaque return type of property 'foo'}}
380+
{} // expected-error {{type '() -> ()' cannot conform to 'P_51641323'; only struct/enum/class types can conform to protocols}}
381+
}
382382
}
383383
}
384384

test/type/subclass_composition.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ func dependentMemberTypes<T : BaseIntAndP2>(
300300

301301
func conformsToAnyObject<T : AnyObject>(_: T) {}
302302
func conformsToP1<T : P1>(_: T) {}
303+
// expected-note@-1 {{required by global function 'conformsToP1' where 'T' = 'P1'}}
303304
func conformsToP2<T : P2>(_: T) {}
304305
func conformsToBaseIntAndP2<T : Base<Int> & P2>(_: T) {}
305306
// expected-note@-1 {{where 'T' = 'FakeDerived'}}
@@ -412,7 +413,7 @@ func conformsTo<T1 : P2, T2 : Base<Int> & P2>(
412413
// expected-note@-2 {{expected an argument list of type '(T)'}}
413414

414415
conformsToP1(p1)
415-
// expected-error@-1 {{protocol type 'P1' cannot conform to 'P1' because only concrete types can conform to protocols}}
416+
// expected-error@-1 {{value of protocol type 'P1' cannot conform to 'P1'; only struct/enum/class types can conform to protocols}}
416417

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

0 commit comments

Comments
 (0)