Skip to content

Commit c47f99a

Browse files
committed
Diag: Use 'Self'-rooted interface types instead of opened archetypes in requirement failure messages
1 parent 8e0e414 commit c47f99a

File tree

4 files changed

+92
-77
lines changed

4 files changed

+92
-77
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,25 @@ bool RequirementFailure::diagnoseAsError() {
359359
const auto *reqDC = getRequirementDC();
360360
auto *genericCtx = getGenericContext();
361361

362-
auto lhs = getLHS();
363-
auto rhs = getRHS();
362+
// Instead of printing archetypes rooted on an opened existential, which
363+
// are currently an implementation detail, have a weird textual
364+
// representation, and may be misleading (a root opened archetype prints like
365+
// an existential type), use the corresponding 'Self'-rooted interface types
366+
// from the requirement, which are more familiar.
367+
const auto lhs = [&] {
368+
if (getLHS()->hasOpenedExistential()) {
369+
return getRequirement().getFirstType();
370+
}
371+
372+
return getLHS();
373+
}();
374+
const auto rhs = [&] {
375+
if (getRHS()->hasOpenedExistential()) {
376+
return getRequirement().getSecondType();
377+
}
378+
379+
return getRHS();
380+
}();
364381

365382
if (auto *OTD = dyn_cast<OpaqueTypeDecl>(AffectedDecl)) {
366383
auto *namingDecl = OTD->getNamingDecl();
@@ -387,7 +404,8 @@ bool RequirementFailure::diagnoseAsError() {
387404
AffectedDecl->getName(), lhs, rhs);
388405
}
389406

390-
emitRequirementNote(reqDC->getAsDecl(), lhs, rhs);
407+
maybeEmitRequirementNote(reqDC->getAsDecl(), lhs, rhs);
408+
391409
return true;
392410
}
393411

@@ -406,8 +424,8 @@ bool RequirementFailure::diagnoseAsNote() {
406424
return true;
407425
}
408426

409-
void RequirementFailure::emitRequirementNote(const Decl *anchor, Type lhs,
410-
Type rhs) const {
427+
void RequirementFailure::maybeEmitRequirementNote(const Decl *anchor, Type lhs,
428+
Type rhs) const {
411429
auto &req = getRequirement();
412430

413431
if (req.getKind() != RequirementKind::SameType) {
@@ -431,6 +449,11 @@ void RequirementFailure::emitRequirementNote(const Decl *anchor, Type lhs,
431449

432450
if (req.getKind() == RequirementKind::Layout ||
433451
rhs->isEqual(req.getSecondType())) {
452+
// If the note is tautological, bail out.
453+
if (lhs->isEqual(req.getFirstType())) {
454+
return;
455+
}
456+
434457
emitDiagnosticAt(anchor, diag::where_requirement_failure_one_subst,
435458
req.getFirstType(), lhs);
436459
return;

lib/Sema/CSDiagnostics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ class RequirementFailure : public FailureDiagnostic {
333333
/// Retrieve generic signature where this parameter originates from.
334334
GenericSignature getSignature(ConstraintLocator *locator);
335335

336-
void emitRequirementNote(const Decl *anchor, Type lhs, Type rhs) const;
336+
void maybeEmitRequirementNote(const Decl *anchor, Type lhs, Type rhs) const;
337337

338338
/// If this is a failure in conditional requirement, retrieve
339339
/// conformance information.

test/Constraints/static_members_on_protocol_in_generic_context.swift

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ struct G<T> : P {
1111
var other: G<T> { fatalError() }
1212
}
1313

14-
extension P where Self == S { // expected-note 24 {{where 'Self' = 'P'}}
14+
extension P where Self == S {
1515
static var property: S { S() }
1616

1717
static var iuoProp: S! { S() }
@@ -31,98 +31,98 @@ extension P where Self == S { // expected-note 24 {{where 'Self' = 'P'}}
3131
}
3232

3333
extension P {
34-
static func genericFn<T>(_: T) -> G<T> where Self == G<T> { // expected-note 5 {{where 'Self' = 'P', 'G<T>' = 'G<Int>}} expected-note 2 {{where 'Self' = 'P', 'G<T>' = 'G<String>'}}
34+
static func genericFn<T>(_: T) -> G<T> where Self == G<T> { // expected-note 5 {{'G<T>' = 'G<Int>}} expected-note 2 {{'G<T>' = 'G<String>'}}
3535
return G<T>()
3636
}
3737

38-
static subscript<T>(t t: T) -> G<T> where Self == G<T> { // expected-note 5 {{where 'Self' = 'P', 'G<T>' = 'G<Int>'}} expected-note 2 {{where 'Self' = 'P', 'G<T>' = 'G<String>'}}
38+
static subscript<T>(t t: T) -> G<T> where Self == G<T> { // expected-note 5 {{'G<T>' = 'G<Int>'}} expected-note 2 {{'G<T>' = 'G<String>'}}
3939
get { G<T>() }
4040
}
4141
}
4242

4343
// References on protocol metatype are only allowed through a leading dot syntax
4444

4545
_ = P.property // expected-error {{static member 'property' cannot be used on protocol metatype 'P.Protocol'}}
46-
// expected-error@-1 {{static property 'property' requires the types 'P' and 'S' be equivalent}}
46+
// expected-error@-1 {{static property 'property' requires the types 'Self' and 'S' be equivalent}}
4747
_ = P.property.other // expected-error {{static member 'property' cannot be used on protocol metatype 'P.Protocol'}}
48-
// expected-error@-1 {{static property 'property' requires the types 'P' and 'S' be equivalent}}
48+
// expected-error@-1 {{static property 'property' requires the types 'Self' and 'S' be equivalent}}
4949
_ = P.iuoProp // expected-error {{static member 'iuoProp' cannot be used on protocol metatype 'P.Protocol'}}
50-
// expected-error@-1 {{static property 'iuoProp' requires the types 'P' and 'S' be equivalent}}
50+
// expected-error@-1 {{static property 'iuoProp' requires the types 'Self' and 'S' be equivalent}}
5151
_ = P.iuoProp.other // expected-error {{static member 'iuoProp' cannot be used on protocol metatype 'P.Protocol'}}
52-
// expected-error@-1 {{static property 'iuoProp' requires the types 'P' and 'S' be equivalent}}
52+
// expected-error@-1 {{static property 'iuoProp' requires the types 'Self' and 'S' be equivalent}}
5353
_ = P.optProp // expected-error {{static member 'optProp' cannot be used on protocol metatype 'P.Protocol'}}
54-
// expected-error@-1 {{static property 'optProp' requires the types 'P' and 'S' be equivalent}}
54+
// expected-error@-1 {{static property 'optProp' requires the types 'Self' and 'S' be equivalent}}
5555
_ = P.optProp?.other // expected-error {{static member 'optProp' cannot be used on protocol metatype 'P.Protocol'}}
56-
// expected-error@-1 {{static property 'optProp' requires the types 'P' and 'S' be equivalent}}
56+
// expected-error@-1 {{static property 'optProp' requires the types 'Self' and 'S' be equivalent}}
5757
_ = P.fnProp // expected-error {{static member 'fnProp' cannot be used on protocol metatype 'P.Protocol'}}
58-
// expected-error@-1 {{static property 'fnProp' requires the types 'P' and 'S' be equivalent}}
58+
// expected-error@-1 {{static property 'fnProp' requires the types 'Self' and 'S' be equivalent}}
5959
_ = P.fnProp() // expected-error {{static member 'fnProp' cannot be used on protocol metatype 'P.Protocol'}}
60-
// expected-error@-1 {{static property 'fnProp' requires the types 'P' and 'S' be equivalent}}
60+
// expected-error@-1 {{static property 'fnProp' requires the types 'Self' and 'S' be equivalent}}
6161
_ = P.fnProp().other // expected-error {{static member 'fnProp' cannot be used on protocol metatype 'P.Protocol'}}
62-
// expected-error@-1 {{static property 'fnProp' requires the types 'P' and 'S' be equivalent}}
62+
// expected-error@-1 {{static property 'fnProp' requires the types 'Self' and 'S' be equivalent}}
6363
_ = P.method() // expected-error {{static member 'method' cannot be used on protocol metatype 'P.Protocol'}}
64-
// expected-error@-1 {{referencing static method 'method()' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
64+
// expected-error@-1 {{referencing static method 'method()' on 'P' requires the types 'Self' and 'S' be equivalent}}
6565
_ = P.method // expected-error {{static member 'method' cannot be used on protocol metatype 'P.Protocol'}}
66-
// expected-error@-1 {{referencing static method 'method()' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
66+
// expected-error@-1 {{referencing static method 'method()' on 'P' requires the types 'Self' and 'S' be equivalent}}
6767
_ = P.method().other // expected-error {{static member 'method' cannot be used on protocol metatype 'P.Protocol'}}
68-
// expected-error@-1 {{referencing static method 'method()' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
68+
// expected-error@-1 {{referencing static method 'method()' on 'P' requires the types 'Self' and 'S' be equivalent}}
6969
_ = P.genericFn(42) // expected-error {{static member 'genericFn' cannot be used on protocol metatype 'P.Protocol'}}
70-
// expected-error@-1 {{static method 'genericFn' requires the types 'P' and 'G<Int>' be equivalent}}
70+
// expected-error@-1 {{static method 'genericFn' requires the types 'Self' and 'G<Int>' be equivalent}}
7171
_ = P.genericFn(42).other // expected-error {{static member 'genericFn' cannot be used on protocol metatype 'P.Protocol'}}
72-
// expected-error@-1 {{static method 'genericFn' requires the types 'P' and 'G<Int>' be equivalent}}
72+
// expected-error@-1 {{static method 'genericFn' requires the types 'Self' and 'G<Int>' be equivalent}}
7373
_ = P[42] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
74-
// expected-error@-1 {{referencing static subscript 'subscript(_:)' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
74+
// expected-error@-1 {{referencing static subscript 'subscript(_:)' on 'P' requires the types 'Self' and 'S' be equivalent}}
7575
_ = P[42].other // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
76-
// expected-error@-1 {{referencing static subscript 'subscript(_:)' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
76+
// expected-error@-1 {{referencing static subscript 'subscript(_:)' on 'P' requires the types 'Self' and 'S' be equivalent}}
7777
_ = P[t: 42] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
78-
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'P' and 'G<Int>' be equivalent}}
78+
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'Self' and 'G<Int>' be equivalent}}
7979
_ = P[t: 42].other // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
80-
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'P' and 'G<Int>' be equivalent}}
80+
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'Self' and 'G<Int>' be equivalent}}
8181

8282
let _: S = P.property // expected-error {{static member 'property' cannot be used on protocol metatype 'P.Protocol'}}
83-
// expected-error@-1 {{static property 'property' requires the types 'P' and 'S' be equivalent}}
83+
// expected-error@-1 {{static property 'property' requires the types 'Self' and 'S' be equivalent}}
8484
let _: S = P.property.other // expected-error {{static member 'property' cannot be used on protocol metatype 'P.Protocol'}}
85-
// expected-error@-1 {{static property 'property' requires the types 'P' and 'S' be equivalent}}
85+
// expected-error@-1 {{static property 'property' requires the types 'Self' and 'S' be equivalent}}
8686
let _: () -> S = P.fnProp // expected-error {{static member 'fnProp' cannot be used on protocol metatype 'P.Protocol'}}
87-
// expected-error@-1 {{static property 'fnProp' requires the types 'P' and 'S' be equivalent}}
87+
// expected-error@-1 {{static property 'fnProp' requires the types 'Self' and 'S' be equivalent}}
8888
let _: S = P.fnProp() // expected-error {{static member 'fnProp' cannot be used on protocol metatype 'P.Protocol'}}
89-
// expected-error@-1 {{static property 'fnProp' requires the types 'P' and 'S' be equivalent}}
89+
// expected-error@-1 {{static property 'fnProp' requires the types 'Self' and 'S' be equivalent}}
9090
let _: S = P.fnProp().other // expected-error {{static member 'fnProp' cannot be used on protocol metatype 'P.Protocol'}}
91-
// expected-error@-1 {{static property 'fnProp' requires the types 'P' and 'S' be equivalent}}
91+
// expected-error@-1 {{static property 'fnProp' requires the types 'Self' and 'S' be equivalent}}
9292
let _: () -> S = P.method // expected-error {{static member 'method' cannot be used on protocol metatype 'P.Protocol'}}
93-
// expected-error@-1 {{referencing static method 'method()' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
93+
// expected-error@-1 {{referencing static method 'method()' on 'P' requires the types 'Self' and 'S' be equivalent}}
9494
let _: S = P.method() // expected-error {{static member 'method' cannot be used on protocol metatype 'P.Protocol'}}
95-
// expected-error@-1 {{referencing static method 'method()' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
95+
// expected-error@-1 {{referencing static method 'method()' on 'P' requires the types 'Self' and 'S' be equivalent}}
9696
let _: S = P.method().other // expected-error {{static member 'method' cannot be used on protocol metatype 'P.Protocol'}}
97-
// expected-error@-1 {{referencing static method 'method()' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
97+
// expected-error@-1 {{referencing static method 'method()' on 'P' requires the types 'Self' and 'S' be equivalent}}
9898
let _: G<Int> = P.genericFn(42) // expected-error {{static member 'genericFn' cannot be used on protocol metatype 'P.Protocol'}}
99-
// expected-error@-1 {{static method 'genericFn' requires the types 'P' and 'G<Int>' be equivalent}}
99+
// expected-error@-1 {{static method 'genericFn' requires the types 'Self' and 'G<Int>' be equivalent}}
100100
let _: G = P.genericFn(42) // expected-error {{static member 'genericFn' cannot be used on protocol metatype 'P.Protocol'}}
101-
// expected-error@-1 {{static method 'genericFn' requires the types 'P' and 'G<Int>' be equivalent}}
101+
// expected-error@-1 {{static method 'genericFn' requires the types 'Self' and 'G<Int>' be equivalent}}
102102
let _: G<String> = P.genericFn(42) // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
103103
// expected-error@-1 {{static member 'genericFn' cannot be used on protocol metatype 'P.Protocol'}}
104-
// expected-error@-2 {{static method 'genericFn' requires the types 'P' and 'G<String>' be equivalent}}
104+
// expected-error@-2 {{static method 'genericFn' requires the types 'Self' and 'G<String>' be equivalent}}
105105
let _: G<Int> = P.genericFn(42).other // expected-error {{static member 'genericFn' cannot be used on protocol metatype 'P.Protocol'}}
106-
// expected-error@-1 {{static method 'genericFn' requires the types 'P' and 'G<Int>' be equivalent}}
106+
// expected-error@-1 {{static method 'genericFn' requires the types 'Self' and 'G<Int>' be equivalent}}
107107
let _: G<String> = P.genericFn(42).other // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
108-
// expected-error@-1 {{static method 'genericFn' requires the types 'P' and 'G<String>' be equivalent}}
108+
// expected-error@-1 {{static method 'genericFn' requires the types 'Self' and 'G<String>' be equivalent}}
109109
// expected-error@-2 {{static member 'genericFn' cannot be used on protocol metatype 'P.Protocol'}}
110110
let _: S = P[42] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
111-
// expected-error@-1 {{referencing static subscript 'subscript(_:)' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
111+
// expected-error@-1 {{referencing static subscript 'subscript(_:)' on 'P' requires the types 'Self' and 'S' be equivalent}}
112112
let _: S = P[42].other // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
113-
// expected-error@-1 {{referencing static subscript 'subscript(_:)' on 'static_members_on_protocol_in_generic_context.P' requires the types 'static_members_on_protocol_in_generic_context.P' and 'S' be equivalent}}
113+
// expected-error@-1 {{referencing static subscript 'subscript(_:)' on 'P' requires the types 'Self' and 'S' be equivalent}}
114114
let _: G<Int> = P[t: 42] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
115-
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'P' and 'G<Int>' be equivalent}}
115+
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'Self' and 'G<Int>' be equivalent}}
116116
let _: G = P[t: 42] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
117-
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'P' and 'G<Int>' be equivalent}}
117+
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'Self' and 'G<Int>' be equivalent}}
118118
let _: G<String> = P[t: 42] // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
119119
// expected-error@-1 {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
120-
// expected-error@-2 {{static subscript 'subscript(t:)' requires the types 'P' and 'G<String>' be equivalent}}
120+
// expected-error@-2 {{static subscript 'subscript(t:)' requires the types 'Self' and 'G<String>' be equivalent}}
121121
let _: G<Int> = P[t: 42].other // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
122-
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'P' and 'G<Int>' be equivalent}}
122+
// expected-error@-1 {{static subscript 'subscript(t:)' requires the types 'Self' and 'G<Int>' be equivalent}}
123123
let _: G<String> = P[t: 42].other // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
124124
// expected-error@-1 {{static member 'subscript' cannot be used on protocol metatype 'P.Protocol'}}
125-
// expected-error@-2 {{static subscript 'subscript(t:)' requires the types 'P' and 'G<String>' be equivalent}}
125+
// expected-error@-2 {{static subscript 'subscript(t:)' requires the types 'Self' and 'G<String>' be equivalent}}
126126

127127
func test<T: P>(_: T) {}
128128

0 commit comments

Comments
 (0)