Skip to content

Commit e3b1f34

Browse files
committed
[CSDiagnostics] Adjust conformance failure diagnostic to check for locatable types
If conformance failure is associated with a `LocatableType`, use its location to anchor the failure.
1 parent e61bf20 commit e3b1f34

File tree

5 files changed

+137
-6
lines changed

5 files changed

+137
-6
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,13 @@ void RequirementFailure::maybeEmitRequirementNote(const Decl *anchor, Type lhs,
611611
req.getFirstType(), lhs, req.getSecondType(), rhs);
612612
}
613613

614+
SourceLoc MissingConformanceFailure::getLoc() const {
615+
if (auto *locatable = dyn_cast<LocatableType>(LHS.getPointer())) {
616+
return locatable->getLoc();
617+
}
618+
return RequirementFailure::getLoc();
619+
}
620+
614621
bool MissingConformanceFailure::diagnoseAsError() {
615622
auto anchor = getAnchor();
616623
auto nonConformingType = getLHS();

lib/Sema/CSDiagnostics.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ class RequirementFailure : public FailureDiagnostic {
259259
Apply = dyn_cast<ApplyExpr>(parentExpr);
260260
}
261261

262+
virtual SourceLoc getLoc() const override {
263+
return FailureDiagnostic::getLoc();
264+
}
265+
262266
unsigned getRequirementIndex() const {
263267
auto reqElt =
264268
getLocator()->castLastElementTo<LocatorPathElt::AnyRequirement>();
@@ -341,6 +345,8 @@ class MissingConformanceFailure final : public RequirementFailure {
341345
#endif
342346
}
343347

348+
virtual SourceLoc getLoc() const override;
349+
344350
bool diagnoseAsError() override;
345351

346352
protected:

test/Constraints/result_builder_diags.swift

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -629,15 +629,37 @@ _ = wrapperifyInfer(true) { x in // Ok
629629

630630
struct DoesNotConform {}
631631

632+
struct List<C> {
633+
typealias T = C
634+
635+
init(@TupleBuilder _: () -> C) {}
636+
}
637+
638+
extension List: P where C: P {}
639+
632640
struct MyView {
633-
@TupleBuilder var value: some P { // expected-error {{return type of property 'value' requires that 'DoesNotConform' conform to 'P'}}
641+
struct Conforms : P {
642+
typealias T = Void
643+
}
644+
645+
@TupleBuilder var value: some P {
646+
// expected-note@-1 {{opaque return type declared here}}
647+
DoesNotConform() // expected-error {{return type of property 'value' requires that 'DoesNotConform' conform to 'P'}}
648+
}
649+
650+
@TupleBuilder var nestedFailures: some P {
634651
// expected-note@-1 {{opaque return type declared here}}
635-
DoesNotConform()
652+
List {
653+
List {
654+
DoesNotConform()
655+
// expected-error@-1 {{return type of property 'nestedFailures' requires that 'DoesNotConform' conform to 'P'}}
656+
}
657+
}
636658
}
637659

638-
@TupleBuilder func test() -> some P { // expected-error {{return type of instance method 'test()' requires that 'DoesNotConform' conform to 'P'}}
660+
@TupleBuilder func test() -> some P {
639661
// expected-note@-1 {{opaque return type declared here}}
640-
DoesNotConform()
662+
DoesNotConform() // expected-error {{return type of instance method 'test()' requires that 'DoesNotConform' conform to 'P'}}
641663
}
642664

643665
@TupleBuilder var emptySwitch: some P {
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// RUN: %target-typecheck-verify-swift -target %target-swift-5.9-abi-triple
2+
3+
protocol Element {
4+
associatedtype Body: Element
5+
6+
@Builder
7+
var body: Body { get }
8+
}
9+
10+
@resultBuilder
11+
struct Builder {
12+
static func buildBlock<C>(_ content: C) -> C {
13+
fatalError()
14+
}
15+
16+
static func buildBlock<each C>(
17+
_ content: repeat each C
18+
) -> TupleContent<repeat each C> {
19+
fatalError()
20+
}
21+
}
22+
23+
struct TupleContent<each Content> {
24+
var content: (repeat each Content)
25+
var body: Never { fatalError() }
26+
}
27+
28+
struct List<Content> {
29+
@Builder var content: Content
30+
31+
var body: Never { fatalError() }
32+
}
33+
34+
extension List: Element where Content: Element {}
35+
36+
public struct For<Data: RandomAccessCollection, Content> {
37+
init(
38+
_ data: Data,
39+
@Builder content: @escaping (Data.Element) -> Content
40+
) {
41+
}
42+
43+
var body: Never { fatalError() }
44+
}
45+
46+
extension For: Element where Content: Element {}
47+
48+
extension Never : Element {
49+
var body: Never { fatalError() }
50+
}
51+
52+
extension TupleContent: Element where repeat each Content: Element {}
53+
54+
struct FakeElement {}
55+
56+
struct Element1: Element { var body: some Element { fatalError() } }
57+
struct Element2: Element { var body: some Element { fatalError() } }
58+
struct Element3: Element { var body: some Element { fatalError() } }
59+
60+
struct Test1: Element {
61+
var body: some Element { // expected-note {{opaque return type declared here}}
62+
List {
63+
FakeElement()
64+
// expected-error@-1 {{return type of property 'body' requires that 'FakeElement' conform to 'Element'}}
65+
}
66+
}
67+
}
68+
69+
struct Test2: Element {
70+
var body: some Element { // expected-note {{opaque return type declared here}}
71+
List {
72+
Element1()
73+
List {
74+
Element2()
75+
FakeElement()
76+
// expected-error@-1 {{return type of property 'body' requires that 'FakeElement' conform to 'Element'}}
77+
Element3()
78+
}
79+
}
80+
}
81+
}
82+
83+
struct Test3: Element {
84+
var body: some Element { // expected-note {{opaque return type declared here}}
85+
List {
86+
For([1, 2, 3]) { _ in
87+
Element1()
88+
List {
89+
Element2()
90+
FakeElement() // expected-error {{return type of property 'body' requires that 'FakeElement' conform to 'Element'}}
91+
}
92+
}
93+
}
94+
}
95+
}

validation-test/compiler_crashers_2_fixed/issue-57241.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ struct S {
88

99
func test() {
1010
ForEach(data) { group in
11-
ForEach(group) { month in // expected-error {{type '()' cannot conform to 'View'}}
12-
// expected-note@-1 {{only concrete types such as structs, enums and classes can conform to protocols}}
11+
ForEach(group) { month in
1312
self.f()
13+
// expected-error@-1 {{type '()' cannot conform to 'View'}}
14+
// expected-note@-2 {{only concrete types such as structs, enums and classes can conform to protocols}}
1415
}
1516
}
1617
}

0 commit comments

Comments
 (0)