Skip to content

Commit 835c2c9

Browse files
committed
[AST] Break recursion in SubstitutionMap::dump too.
1 parent ad503e9 commit 835c2c9

File tree

3 files changed

+83
-31
lines changed

3 files changed

+83
-31
lines changed

include/swift/AST/SubstitutionMap.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,17 @@ class SubstitutionMap {
7171
/// signature nor any replacement types/conformances.
7272
Storage *storage = nullptr;
7373

74+
public:
7475
/// Retrieve the array of replacement types, which line up with the
7576
/// generic parameters.
7677
///
7778
/// Note that the types may be null, for cases where the generic parameter
7879
/// is concrete but hasn't been queried yet.
80+
///
81+
/// Prefer \c getReplacementTypes, this is public for printing purposes.
7982
ArrayRef<Type> getReplacementTypesBuffer() const;
8083

84+
private:
8185
MutableArrayRef<Type> getReplacementTypesBuffer();
8286

8387
/// Retrieve a mutable reference to the buffer of conformances.

lib/AST/ASTDumper.cpp

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2800,6 +2800,11 @@ static void dumpProtocolConformanceRec(
28002800
unsigned indent,
28012801
llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited);
28022802

2803+
static void dumpSubstitutionMapRec(
2804+
SubstitutionMap map, llvm::raw_ostream &out,
2805+
SubstitutionMap::DumpStyle style, unsigned indent,
2806+
llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited);
2807+
28032808
static void dumpProtocolConformanceRefRec(
28042809
const ProtocolConformanceRef conformance, llvm::raw_ostream &out,
28052810
unsigned indent,
@@ -2905,8 +2910,9 @@ static void dumpProtocolConformanceRec(
29052910
break;
29062911

29072912
out << '\n';
2908-
conf->getSubstitutionMap().dump(out, SubstitutionMap::DumpStyle::Full,
2909-
indent + 2);
2913+
dumpSubstitutionMapRec(conf->getSubstitutionMap(), out,
2914+
SubstitutionMap::DumpStyle::Full, indent + 2,
2915+
visited);
29102916
out << '\n';
29112917
for (auto subReq : conf->getConditionalRequirements()) {
29122918
out.indent(indent + 2);
@@ -2922,31 +2928,11 @@ static void dumpProtocolConformanceRec(
29222928
PrintWithColorRAII(out, ParenthesisColor) << ')';
29232929
}
29242930

2925-
void ProtocolConformanceRef::dump() const {
2926-
dump(llvm::errs());
2927-
llvm::errs() << '\n';
2928-
}
2929-
2930-
void ProtocolConformanceRef::dump(llvm::raw_ostream &out,
2931-
unsigned indent) const {
2932-
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
2933-
dumpProtocolConformanceRefRec(*this, out, indent, visited);
2934-
}
2935-
void ProtocolConformance::dump() const {
2936-
auto &out = llvm::errs();
2937-
dump(out);
2938-
out << '\n';
2939-
}
2940-
2941-
void ProtocolConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
2942-
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
2943-
dumpProtocolConformanceRec(this, out, indent, visited);
2944-
}
2945-
2946-
void SubstitutionMap::dump(llvm::raw_ostream &out,
2947-
SubstitutionMap::DumpStyle style,
2948-
unsigned indent) const {
2949-
auto *genericSig = getGenericSignature();
2931+
static void dumpSubstitutionMapRec(
2932+
SubstitutionMap map, llvm::raw_ostream &out,
2933+
SubstitutionMap::DumpStyle style, unsigned indent,
2934+
llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited) {
2935+
auto *genericSig = map.getGenericSignature();
29502936
out.indent(indent);
29512937

29522938
auto printParen = [&](char p) {
@@ -2962,7 +2948,8 @@ void SubstitutionMap::dump(llvm::raw_ostream &out,
29622948

29632949
genericSig->print(out);
29642950
auto genericParams = genericSig->getGenericParams();
2965-
auto replacementTypes = getReplacementTypesBuffer();
2951+
auto replacementTypes =
2952+
static_cast<const SubstitutionMap &>(map).getReplacementTypesBuffer();
29662953
for (unsigned i : indices(genericParams)) {
29672954
if (style == SubstitutionMap::DumpStyle::Minimal) {
29682955
out << " ";
@@ -2985,9 +2972,7 @@ void SubstitutionMap::dump(llvm::raw_ostream &out,
29852972
if (style == SubstitutionMap::DumpStyle::Minimal)
29862973
return;
29872974

2988-
// We only really need to print a conformance once across this whole map.
2989-
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
2990-
auto conformances = getConformances();
2975+
auto conformances = map.getConformances();
29912976
for (const auto &req : genericSig->getRequirements()) {
29922977
if (req.getKind() != RequirementKind::Conformance)
29932978
continue;
@@ -3006,6 +2991,33 @@ void SubstitutionMap::dump(llvm::raw_ostream &out,
30062991
}
30072992
}
30082993

2994+
void ProtocolConformanceRef::dump() const {
2995+
dump(llvm::errs());
2996+
llvm::errs() << '\n';
2997+
}
2998+
2999+
void ProtocolConformanceRef::dump(llvm::raw_ostream &out,
3000+
unsigned indent) const {
3001+
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
3002+
dumpProtocolConformanceRefRec(*this, out, indent, visited);
3003+
}
3004+
void ProtocolConformance::dump() const {
3005+
auto &out = llvm::errs();
3006+
dump(out);
3007+
out << '\n';
3008+
}
3009+
3010+
void ProtocolConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
3011+
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
3012+
dumpProtocolConformanceRec(this, out, indent, visited);
3013+
}
3014+
3015+
void SubstitutionMap::dump(llvm::raw_ostream &out, DumpStyle style,
3016+
unsigned indent) const {
3017+
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
3018+
dumpSubstitutionMapRec(*this, out, style, indent, visited);
3019+
}
3020+
30093021
void SubstitutionMap::dump() const {
30103022
dump(llvm::errs());
30113023
llvm::errs() << "\n";

test/Driver/debug-generic-signatures.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ protocol P2 {
2121
associatedtype B: P2 where Self.A.A == Self.B.A
2222
}
2323

24+
// Simpler recursion
25+
// CHECK: Generic signature: <Self where Self : P3>
26+
// CHECK-NEXT: Canonical generic signature: <τ_0_0 where τ_0_0 : P3>
27+
// CHECK-LABEL: main.(file).P3@
28+
// CHECK: Requirement signature: <Self where Self.A : P3>
29+
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.A : P3>
30+
protocol P3 {
31+
associatedtype A: P3
32+
}
33+
2434
// CHECK-LABEL: StructDecl name=Basic
2535
// CHECK: (normal_conformance type=Basic protocol=P1
2636
// CHECK-NEXT: (assoc_type req=A type=Basic.A)
@@ -118,3 +128,29 @@ extension Super: P2 where T: P2, U: P2 {
118128
// CHECK-NEXT: conforms_to: T P2
119129
// CHECK-NEXT: conforms_to: U P2)))
120130
class Sub: Super<NonRecur, Recur> {}
131+
132+
// Specialization of a recursive conformance should be okay: recursion detection
133+
// should work through SubstitutionMaps.
134+
135+
// CHECK-LABEL: StructDecl name=RecurGeneric
136+
// CHECK-NEXT: (normal_conformance type=RecurGeneric<T> protocol=P3
137+
// CHECK-NEXT: (assoc_type req=A type=RecurGeneric<T>.A)
138+
// CHECK-NEXT: (normal_conformance type=RecurGeneric<T> protocol=P3 (details printed above)))
139+
struct RecurGeneric<T: P3>: P3 {
140+
typealias A = RecurGeneric<T>
141+
}
142+
143+
// CHECK-LABEL: StructDecl name=Specialize
144+
// CHECK-NEXT: (normal_conformance type=Specialize protocol=P3
145+
// CHECK-NEXT: (assoc_type req=A type=Specialize.A)
146+
// CHECK-NEXT: (specialized_conformance type=Specialize.A protocol=P3
147+
// CHECK-NEXT: (substitution_map generic_signature=<T where T : P3>
148+
// CHECK-NEXT: (substitution T -> Specialize)
149+
// CHECK-NEXT: (conformance type=T
150+
// CHECK-NEXT: (normal_conformance type=Specialize protocol=P3 (details printed above))))
151+
// CHECK-NEXT: (normal_conformance type=RecurGeneric<T> protocol=P3
152+
// CHECK-NEXT: (assoc_type req=A type=RecurGeneric<T>.A)
153+
// CHECK-NEXT: (normal_conformance type=RecurGeneric<T> protocol=P3 (details printed above)))))
154+
struct Specialize: P3 {
155+
typealias A = RecurGeneric<Specialize>
156+
}

0 commit comments

Comments
 (0)