Skip to content

Commit a826da5

Browse files
committed
[Sema] Fixits for assoc. type restatement hints should account for where clauses
1 parent ca686a5 commit a826da5

File tree

4 files changed

+51
-13
lines changed

4 files changed

+51
-13
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,8 @@ class alignas(RequirementRepr) TrailingWhereClause final :
14351435
return SourceRange(WhereLoc,
14361436
getRequirements().back().getSourceRange().End);
14371437
}
1438+
1439+
void print(llvm::raw_ostream &OS, bool printWhereKeyword) const;
14381440
};
14391441

14401442
// A private class for forcing exact field layout.

lib/AST/ASTDumper.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,23 @@ void RequirementRepr::print(ASTPrinter &out) const {
164164
printImpl(out, /*AsWritten=*/true);
165165
}
166166

167+
static void printTrailingRequirements(ASTPrinter &Printer,
168+
ArrayRef<RequirementRepr> Reqs,
169+
bool printWhereKeyword) {
170+
if (Reqs.empty()) return;
171+
172+
if (printWhereKeyword)
173+
Printer << " where ";
174+
interleave(
175+
Reqs,
176+
[&](const RequirementRepr &req) {
177+
Printer.callPrintStructurePre(PrintStructureKind::GenericRequirement);
178+
req.print(Printer);
179+
Printer.printStructurePost(PrintStructureKind::GenericRequirement);
180+
},
181+
[&] { Printer << ", "; });
182+
}
183+
167184
void GenericParamList::print(llvm::raw_ostream &OS) const {
168185
OS << '<';
169186
interleave(*this,
@@ -176,14 +193,9 @@ void GenericParamList::print(llvm::raw_ostream &OS) const {
176193
},
177194
[&] { OS << ", "; });
178195

179-
if (!getRequirements().empty()) {
180-
OS << " where ";
181-
interleave(getRequirements(),
182-
[&](const RequirementRepr &req) {
183-
req.print(OS);
184-
},
185-
[&] { OS << ", "; });
186-
}
196+
StreamPrinter Printer(OS);
197+
printTrailingRequirements(Printer, getRequirements(),
198+
/*printWhereKeyword*/true);
187199
OS << '>';
188200
}
189201

@@ -192,6 +204,13 @@ void GenericParamList::dump() const {
192204
llvm::errs() << '\n';
193205
}
194206

207+
void TrailingWhereClause::print(llvm::raw_ostream &OS,
208+
bool printWhereKeyword) const {
209+
StreamPrinter Printer(OS);
210+
printTrailingRequirements(Printer, getRequirements(),
211+
printWhereKeyword);
212+
}
213+
195214
static void printGenericParameters(raw_ostream &OS, GenericParamList *Params) {
196215
if (!Params)
197216
return;
@@ -660,9 +679,7 @@ namespace {
660679
}
661680
if (auto whereClause = decl->getTrailingWhereClause()) {
662681
OS << " where requirements: ";
663-
interleave(whereClause->getRequirements(),
664-
[&](const RequirementRepr &req) { req.print(OS); },
665-
[&] { OS << ", "; });
682+
whereClause->print(OS, /*printWhereKeyword*/false);
666683
}
667684
if (decl->overriddenDeclsComputed()) {
668685
OS << " overridden=";

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3934,8 +3934,8 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
39343934

39353935
// Retrieve the set of requirements that a given associated type declaration
39363936
// produces, in the form that would be seen in the where clause.
3937-
auto getAssociatedTypeReqs = [&](AssociatedTypeDecl *assocType,
3938-
const char *start) {
3937+
const auto getAssociatedTypeReqs = [&](const AssociatedTypeDecl *assocType,
3938+
const char *start) {
39393939
std::string result;
39403940
{
39413941
llvm::raw_string_ostream out(result);
@@ -3949,6 +3949,13 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
39493949
}, [&] {
39503950
out << ", ";
39513951
});
3952+
3953+
if (const auto whereClause = assocType->getTrailingWhereClause()) {
3954+
if (!assocType->getInherited().empty())
3955+
out << ", ";
3956+
3957+
whereClause->print(out, /*printWhereKeyword*/false);
3958+
}
39523959
}
39533960
return result;
39543961
};

test/Generics/associated_type_where_clause_hints.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ struct X1 { }
99

1010
protocol P1 {
1111
associatedtype A // expected-note 2{{'A' declared here}}
12+
associatedtype A2 // expected-note {{'A2' declared here}}
13+
associatedtype A3 // expected-note {{'A3' declared here}}
14+
associatedtype A4 // expected-note {{'A4' declared here}}
1215
}
1316

1417
// A typealias in a subprotocol should be written as a same-type
@@ -21,6 +24,13 @@ protocol P2 : P1 {
2124
// should be written via a where clause.
2225
protocol P3a : P1 {
2326
associatedtype A: P0, P0b // expected-warning{{redeclaration of associated type 'A' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{18-18= where A: P0, A: P0b}}{{3-29=}}
27+
associatedtype A2: P0, P0b where A2.A == Never, A2: P1 // expected-warning{{redeclaration of associated type 'A2' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{18-18= where A2: P0, A2: P0b, A2.A == Never, A2 : P1}}{{3-58=}}
28+
associatedtype A3 where A3: P0 // expected-warning{{redeclaration of associated type 'A3' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{18-18= where A3 : P0}}{{3-34=}}
29+
30+
// expected-warning@+1 {{redeclaration of associated type 'A4' from protocol 'P1' is better expressed as a 'where' clause on the protocol}}{{18-18= where A4: P0, A4 : Collection, A4.Element == A4.Index, A4.SubSequence == A4}}{{3-52=}}
31+
associatedtype A4: P0 where A4: Collection,
32+
A4.Element == A4.Index,
33+
A4.SubSequence == A4 // {{3-52=}} is this line, so it is correct.
2434
}
2535

2636
// ... unless it has adds a default type witness
@@ -30,10 +40,12 @@ protocol P3b : P1 {
3040

3141
protocol P4: P1 {
3242
associatedtype B // expected-note{{'B' declared here}}
43+
associatedtype B2 // expected-note{{'B2' declared here}}
3344
}
3445

3546
protocol P5: P4 where A: P0 {
3647
typealias B = X1 // expected-warning{{typealias overriding associated type 'B' from protocol 'P4' is better expressed as same-type constraint on the protocol}}{{28-28=, B == X1}}{{3-20=}}
48+
associatedtype B2: P5 // expected-warning{{redeclaration of associated type 'B2' from protocol 'P4' is better expressed as a 'where' clause on the protocol}}{{28-28=, B2: P5}} {{3-25=}}
3749
}
3850

3951

0 commit comments

Comments
 (0)