Skip to content

Commit 173e452

Browse files
committed
[Diagnostics] Adjust wording of type_cannot_conform error message.
1 parent 73a218f commit 173e452

File tree

9 files changed

+33
-26
lines changed

9 files changed

+33
-26
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,8 +1661,9 @@ ERROR(use_of_equal_instead_of_equality,none,
16611661
"use of '=' in a boolean context, did you mean '=='?", ())
16621662

16631663
ERROR(type_cannot_conform, none,
1664-
"%0 type %1 cannot conform to %2; only struct/enum/class "
1665-
"types can conform to protocols", (StringRef, Type, Type))
1664+
"%select{|protocol }0type %1 cannot conform to %2; "
1665+
"only struct/enum/class types can conform to protocols",
1666+
(bool, Type, Type))
16661667
ERROR(protocol_does_not_conform_static,none,
16671668
"%0 cannot be used as a type conforming to protocol %1 because %1 "
16681669
"has static requirements",

lib/Sema/CSDiagnostics.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -576,21 +576,8 @@ bool MissingConformanceFailure::diagnoseAsError() {
576576
return true;
577577
}
578578

579-
// Diagnose types that cannot conform to protocols.
580-
Optional<StringRef> prohibitedTypeKind = None;
581-
if (nonConformingType->is<AnyFunctionType>())
582-
prohibitedTypeKind = "function";
583-
else if (nonConformingType->is<TupleType>())
584-
prohibitedTypeKind = "tuple";
585-
else if (nonConformingType->isExistentialType())
586-
prohibitedTypeKind = "protocol";
587-
else if (nonConformingType->is<AnyMetatypeType>())
588-
prohibitedTypeKind = "metatype";
589-
590-
if (prohibitedTypeKind.hasValue()) {
591-
emitDiagnostic(anchor->getLoc(), diag::type_cannot_conform,
592-
*prohibitedTypeKind, nonConformingType, protocolType);
593-
return true;
579+
if (diagnoseTypeCannotConform(anchor, nonConformingType, protocolType)) {
580+
return true;
594581
}
595582

596583
if (atParameterPos) {
@@ -608,6 +595,21 @@ bool MissingConformanceFailure::diagnoseAsError() {
608595
return RequirementFailure::diagnoseAsError();
609596
}
610597

598+
bool MissingConformanceFailure::diagnoseTypeCannotConform(Expr *anchor,
599+
Type nonConformingType, Type protocolType) const {
600+
if (nonConformingType->is<AnyFunctionType>() ||
601+
nonConformingType->is<TupleType>() ||
602+
nonConformingType->isExistentialType() ||
603+
nonConformingType->is<AnyMetatypeType>()) {
604+
emitDiagnostic(anchor->getLoc(), diag::type_cannot_conform,
605+
nonConformingType->isExistentialType(), nonConformingType,
606+
protocolType);
607+
return true;
608+
}
609+
610+
return false;
611+
}
612+
611613
Optional<Diag<Type, Type>> GenericArgumentsMismatchFailure::getDiagnosticFor(
612614
ContextualTypePurpose context) {
613615
switch (context) {

lib/Sema/CSDiagnostics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,10 @@ class MissingConformanceFailure final : public RequirementFailure {
356356
DiagAsNote getDiagnosticAsNote() const override {
357357
return diag::candidate_types_conformance_requirement;
358358
}
359+
360+
private:
361+
bool diagnoseTypeCannotConform(Expr *anchor, Type nonConformingType,
362+
Type protocolType) const;
359363
};
360364

361365
/// 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::type_cannot_conform, "protocol",
3973+
diags.diagnose(ComplainLoc, diag::type_cannot_conform, true,
39743974
T, Proto->getDeclaredType());
39753975
return;
39763976
}

test/Constraints/diagnostics.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ f0(i, i,
4747

4848

4949
// Cannot conform to protocols.
50-
f5(f4) // expected-error {{function type '(Int) -> Int' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
51-
f5((1, "hello")) // expected-error {{tuple type '(Int, String)' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
52-
f5(Int.self) // expected-error {{metatype type 'Int.Type' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
50+
f5(f4) // expected-error {{type '(Int) -> Int' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
51+
f5((1, "hello")) // expected-error {{type '(Int, String)' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
52+
f5(Int.self) // expected-error {{type 'Int.Type' cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
5353

5454
// Tuple element not convertible.
5555
f0(i,
@@ -99,7 +99,7 @@ func f8<T:P2>(_ n: T, _ f: @escaping (T) -> T) {}
9999
f8(3, f4) // expected-error {{argument type 'Int' does not conform to expected type 'P2'}}
100100
typealias Tup = (Int, Double)
101101
func f9(_ x: Tup) -> Tup { return x }
102-
f8((1,2.0), f9) // expected-error {{tuple type 'Tup' (aka '(Int, Double)') cannot conform to 'P2'; only struct/enum/class types can conform to protocols}}
102+
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}}
103103

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

test/Constraints/function_builder_diags.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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 {{metatype type 'Label<Any>.Type' cannot conform to 'P'; only struct/enum/class types can conform to protocols}}
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/type/opaque.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ protocol P_51641323 {
377377
func rdar_51641323() {
378378
struct Foo: P_51641323 {
379379
var foo: some P_51641323 { {} }
380-
// expected-error@-1 {{function type '() -> ()' cannot conform to 'P_51641323'; only struct/enum/class types can conform to protocols}}
380+
// expected-error@-1 {{type '() -> ()' cannot conform to 'P_51641323'; only struct/enum/class types can conform to protocols}}
381381
}
382382
}
383383

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// RUN: %target-swift-frontend %s -typecheck -verify
22

33
var d = [String:String]()
4-
_ = "\(d.map{ [$0 : $0] })" // expected-error {{tuple type '(key: String, value: String)' cannot conform to 'Hashable'; only struct/enum/class types can conform to protocols}}
4+
_ = "\(d.map{ [$0 : $0] })" // expected-error {{type '(key: String, value: String)' cannot conform to 'Hashable'; only struct/enum/class types can conform to protocols}}

validation-test/compiler_crashers_2_fixed/0196-rdar48937223.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ protocol P {}
55
func fn<T, U: P>(_ arg1: T, arg2: (T) -> U) {}
66

77
func test(str: String) {
8-
fn(str) { arg in // expected-error {{tuple type '()' cannot conform to 'P'; only struct/enum/class types can conform to protocols}}
8+
fn(str) { arg in // expected-error {{type '()' cannot conform to 'P'; only struct/enum/class types can conform to protocols}}
99
<#FOO#> // expected-error {{editor placeholder in source file}}
1010
}
1111
}

0 commit comments

Comments
 (0)