Skip to content

Commit 718f9f0

Browse files
committed
Improve type USR generation and inheritance dumps.
- For type USRs, use `mapTypeOutOfContext()` to replace primary archetypes with type parameters. If the type contains local archetypes, replace them with their existential upper bounds. - For inheritance of types, print the derived semantic information instead of the inheritance list as it is written. - Dump conformance requirements as protocol decl USRs instead of type USRs, since the latter involves an existential conversion that loses suppressed protocols. - Fix a small bug in conformance dumping where the `MemberLoading` field wasn't propagated to the nested printer, which caused protocols to be dumped as simple names instead of USRs.
1 parent d61c21b commit 718f9f0

File tree

2 files changed

+116
-26
lines changed

2 files changed

+116
-26
lines changed

lib/AST/ASTDumper.cpp

Lines changed: 104 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,15 @@ std::string typeUSR(Type type) {
234234
return "";
235235

236236
if (type->hasArchetype()) {
237-
// We can't generate USRs for types that contain archetypes. Replace them
238-
// with their interface types.
237+
type = type->mapTypeOutOfContext();
238+
}
239+
if (type->hasLocalArchetype()) {
240+
// If we have local archetypes, we can't mangle those. Replace them with
241+
// their existential upper bounds, which loses information but is probably
242+
// close enough for most purposes.
239243
type = type.transformRec([&](TypeBase *t) -> std::optional<Type> {
240-
if (auto AT = dyn_cast<ArchetypeType>(t)) {
241-
return AT->getInterfaceType();
244+
if (auto LAT = dyn_cast<LocalArchetypeType>(t)) {
245+
return LAT->getExistentialType();
242246
}
243247
return std::nullopt;
244248
});
@@ -1270,11 +1274,25 @@ namespace {
12701274

12711275
printField(requirement.getKind(), Label::optional("kind"));
12721276

1273-
if (requirement.getKind() != RequirementKind::Layout
1274-
&& requirement.getSecondType())
1275-
printTypeField(requirement.getSecondType(),
1276-
Label::optional("second_type"), opts);
1277-
else if (requirement.getLayoutConstraint())
1277+
if (requirement.getKind() != RequirementKind::Layout &&
1278+
requirement.getSecondType()) {
1279+
if (Writer.isParsable()) {
1280+
// If this is a conformance requirement, print the USR of the protocol
1281+
// decl instead of the type. The type USR for a protocol is based on
1282+
// the equivalent expanded existential, which drops suppressed
1283+
// protocols.
1284+
if (requirement.getKind() == RequirementKind::Conformance) {
1285+
printReferencedDeclField(requirement.getProtocolDecl(),
1286+
Label::optional("protocol"));
1287+
} else {
1288+
printTypeField(requirement.getSecondType(),
1289+
Label::optional("second_type"), opts);
1290+
}
1291+
} else {
1292+
printTypeField(requirement.getSecondType(),
1293+
Label::optional("second_type"), opts);
1294+
}
1295+
} else if (requirement.getLayoutConstraint())
12781296
printFieldQuoted(requirement.getLayoutConstraint(),
12791297
Label::optional("layout"));
12801298

@@ -1925,6 +1943,62 @@ namespace {
19251943
}
19261944
}
19271945

1946+
void printInheritance(const IterableDeclContext *DC) {
1947+
if (!(Writer.isParsable() && isTypeChecked())) {
1948+
// If the output is not parsable or we're not type-checked, just print
1949+
// the inheritance list as written.
1950+
switch (DC->getIterableContextKind()) {
1951+
case IterableDeclContextKind::NominalTypeDecl:
1952+
printInherited(cast<NominalTypeDecl>(DC)->getInherited());
1953+
break;
1954+
case IterableDeclContextKind::ExtensionDecl:
1955+
printInherited(cast<ExtensionDecl>(DC)->getInherited());
1956+
break;
1957+
}
1958+
return;
1959+
}
1960+
1961+
// For parsable, type-checked output, print a more structured
1962+
// representation of the data.
1963+
printRecArbitrary(
1964+
[&](Label label) {
1965+
printHead("inheritance", FieldLabelColor, label);
1966+
1967+
SmallPtrSet<const ProtocolConformance *, 4> dumped;
1968+
printList(
1969+
DC->getLocalConformances(),
1970+
[&](auto conformance, Label label) {
1971+
printRec(conformance, dumped, label);
1972+
},
1973+
Label::always("conformances"));
1974+
1975+
if (auto CD = dyn_cast<ClassDecl>(DC); CD && CD->hasSuperclass()) {
1976+
printReferencedDeclField(CD->getSuperclassDecl(),
1977+
Label::always("superclass_decl_usr"));
1978+
}
1979+
1980+
if (auto ED = dyn_cast<EnumDecl>(DC); ED && ED->hasRawType()) {
1981+
printTypeField(ED->getRawType(), Label::always("raw_type"));
1982+
}
1983+
1984+
if (auto PD = dyn_cast<ProtocolDecl>(DC)) {
1985+
printList(
1986+
PD->getAllInheritedProtocols(),
1987+
[&](auto inherited, Label label) {
1988+
printReferencedDeclField(inherited, label);
1989+
},
1990+
Label::always("protocols"));
1991+
if (PD->hasSuperclass()) {
1992+
printReferencedDeclField(PD->getSuperclassDecl(),
1993+
Label::always("superclass_decl_usr"));
1994+
}
1995+
}
1996+
1997+
printFoot();
1998+
},
1999+
Label::always("inherits"));
2000+
}
2001+
19282002
void printInherited(InheritedTypes Inherited) {
19292003
if (Writer.isParsable()) {
19302004
printList(
@@ -2260,13 +2334,13 @@ namespace {
22602334
switch (IDC->getIterableContextKind()) {
22612335
case IterableDeclContextKind::NominalTypeDecl: {
22622336
const auto NTD = cast<NominalTypeDecl>(IDC);
2263-
printInherited(NTD->getInherited());
2337+
printInheritance(NTD);
22642338
printWhereRequirements(NTD);
22652339
break;
22662340
}
22672341
case IterableDeclContextKind::ExtensionDecl:
22682342
const auto ED = cast<ExtensionDecl>(IDC);
2269-
printInherited(ED->getInherited());
2343+
printInheritance(ED);
22702344
printWhereRequirements(ED);
22712345
break;
22722346
}
@@ -5765,27 +5839,33 @@ class PrintConformance : public PrintBase {
57655839

57665840
void PrintBase::printRec(SubstitutionMap map, VisitedConformances &visited,
57675841
Label label) {
5768-
printRecArbitrary([&](Label label) {
5769-
PrintConformance(Writer)
5770-
.visitSubstitutionMap(map, SubstitutionMap::DumpStyle::Full, visited,
5771-
label);
5772-
}, label);
5842+
printRecArbitrary(
5843+
[&](Label label) {
5844+
PrintConformance(Writer, MemberLoading)
5845+
.visitSubstitutionMap(map, SubstitutionMap::DumpStyle::Full,
5846+
visited, label);
5847+
},
5848+
label);
57735849
}
57745850

57755851
void PrintBase::printRec(const ProtocolConformanceRef &ref,
57765852
VisitedConformances &visited, Label label) {
5777-
printRecArbitrary([&](Label label) {
5778-
PrintConformance(Writer)
5779-
.visitProtocolConformanceRef(ref, visited, label);
5780-
}, label);
5853+
printRecArbitrary(
5854+
[&](Label label) {
5855+
PrintConformance(Writer, MemberLoading)
5856+
.visitProtocolConformanceRef(ref, visited, label);
5857+
},
5858+
label);
57815859
}
57825860

57835861
void PrintBase::printRec(const ProtocolConformance *conformance,
57845862
VisitedConformances &visited, Label label) {
5785-
printRecArbitrary([&](Label label) {
5786-
PrintConformance(Writer)
5787-
.visitProtocolConformance(conformance, visited, label);
5788-
}, label);
5863+
printRecArbitrary(
5864+
[&](Label label) {
5865+
PrintConformance(Writer, MemberLoading)
5866+
.visitProtocolConformance(conformance, visited, label);
5867+
},
5868+
label);
57895869
}
57905870

57915871
} // end anonymous namespace

test/Frontend/ast-dump-json-no-crash.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,8 @@ struct Pack<each T> {
341341
func f(_ t: repeat each T) {
342342
repeat g(each t)
343343
}
344+
func g<U>(_ t: U) {}
344345
}
345-
// FIXME: USR generation crashes if this is a member of Pack<each T> above!
346-
func g<U>(_ t: U) {}
347346

348347
func tuplify<each T>(_ value: repeat each T) -> (repeat each T) {
349348
return (repeat each value)
@@ -353,6 +352,17 @@ func example<each T>(_ value: repeat each T) {
353352
repeat print(each abstractTuple)
354353
}
355354

355+
func anySeq<T>(_ type: T.Type = T.self) -> any Sequence<T> { [] }
356+
func anySeqUser() {
357+
let s = anySeq(Int.self)
358+
let iter = s.makeIterator()
359+
}
360+
func opaqueSeq<T>(_ type: T.Type = T.self) -> some Sequence<T> { [] }
361+
func opaqueSeqUser() {
362+
let s = opaqueSeq(Int.self)
363+
let iter = s.makeIterator()
364+
}
365+
356366
let x = 10
357367
func zz1b() {
358368
_ = type(of: x)

0 commit comments

Comments
 (0)