Skip to content

Commit a3993f9

Browse files
authored
Merge pull request swiftlang#80498 from allevato/json-usr-fixes
[AST] More JSON AST dump improvements.
2 parents 8226f20 + 5be2498 commit a3993f9

File tree

7 files changed

+316
-145
lines changed

7 files changed

+316
-145
lines changed

lib/AST/ASTDumper.cpp

Lines changed: 212 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,33 @@ class escaping_ostream : public raw_ostream {
200200
virtual void anchor() override {}
201201
};
202202

203+
/// Replaces any local archetypes in the given type with their equivalent
204+
/// existential upper bounds so that they can be passed to the AST mangler. This
205+
/// loses information but is probably sufficient for most questions about these
206+
/// types that consumers of the JSON AST would ask.
207+
Type replaceLocalArchetypesWithExistentials(Type type) {
208+
return type.transformRec([&](TypeBase *t) -> std::optional<Type> {
209+
if (auto LAT = dyn_cast<LocalArchetypeType>(t)) {
210+
return LAT->getExistentialType();
211+
}
212+
return std::nullopt;
213+
});
214+
}
215+
216+
/// Replaces any opaque type archetypes in the given type with their equivalent
217+
/// existential upper bounds. This is used when dumping the mapping of all
218+
/// opaque types in the source file so that their conformances can be more
219+
/// easily reasoned about without having to find the declaring opaque result
220+
/// type deeper in the AST.
221+
Type replaceOpaqueArchetypesWithExistentials(Type type) {
222+
return type.transformRec([&](TypeBase *t) -> std::optional<Type> {
223+
if (auto OT = dyn_cast<OpaqueTypeArchetypeType>(t)) {
224+
return OT->getExistentialType();
225+
}
226+
return std::nullopt;
227+
});
228+
}
229+
203230
/// Returns the USR of the given declaration. Gracefully returns an empty
204231
/// string if D is null or invalid.
205232
std::string declUSR(const Decl *D) {
@@ -234,14 +261,10 @@ std::string typeUSR(Type type) {
234261
return "";
235262

236263
if (type->hasArchetype()) {
237-
// We can't generate USRs for types that contain archetypes. Replace them
238-
// with their interface types.
239-
type = type.transformRec([&](TypeBase *t) -> std::optional<Type> {
240-
if (auto AT = dyn_cast<ArchetypeType>(t)) {
241-
return AT->getInterfaceType();
242-
}
243-
return std::nullopt;
244-
});
264+
type = type->mapTypeOutOfContext();
265+
}
266+
if (type->hasLocalArchetype()) {
267+
type = replaceLocalArchetypesWithExistentials(type);
245268
}
246269

247270
std::string usr;
@@ -628,6 +651,21 @@ static StringRef getDumpString(ExplicitSafety safety) {
628651
return "unsafe";
629652
}
630653
}
654+
static StringRef getDumpString(ConformanceEntryKind kind) {
655+
switch (kind) {
656+
case ConformanceEntryKind::Inherited:
657+
return "inherited";
658+
case ConformanceEntryKind::Explicit:
659+
return "explicit";
660+
case ConformanceEntryKind::PreMacroExpansion:
661+
return "pre_macro_expansion";
662+
case ConformanceEntryKind::Synthesized:
663+
return "synthesized";
664+
case ConformanceEntryKind::Implied:
665+
return "implied";
666+
}
667+
llvm_unreachable("unhandled ConformanceEntryKind");
668+
}
631669
static StringRef getDumpString(StringRef s) {
632670
return s;
633671
}
@@ -1251,6 +1289,40 @@ namespace {
12511289
void printRec(const ProtocolConformance *conformance,
12521290
VisitedConformances &visited, Label label);
12531291

1292+
// Print a field that describes the actor isolation associated with an AST
1293+
// node.
1294+
void printIsolation(const ActorIsolation &isolation) {
1295+
switch (isolation) {
1296+
case ActorIsolation::Unspecified:
1297+
case ActorIsolation::NonisolatedUnsafe:
1298+
break;
1299+
1300+
case ActorIsolation::Nonisolated:
1301+
printFlag(true, "nonisolated", CapturesColor);
1302+
break;
1303+
1304+
case ActorIsolation::Erased:
1305+
printFlag(true, "dynamically_isolated", CapturesColor);
1306+
break;
1307+
1308+
case ActorIsolation::CallerIsolationInheriting:
1309+
printFlag(true, "isolated_to_caller_isolation", CapturesColor);
1310+
break;
1311+
1312+
case ActorIsolation::ActorInstance:
1313+
printReferencedDeclWithContextField(isolation.getActorInstance(),
1314+
Label::always("actor_isolated"),
1315+
CapturesColor);
1316+
break;
1317+
1318+
case ActorIsolation::GlobalActor:
1319+
printTypeField(isolation.getGlobalActor(),
1320+
Label::always("global_actor_isolated"), PrintOptions(),
1321+
CapturesColor);
1322+
break;
1323+
}
1324+
}
1325+
12541326
/// Print a requirement node.
12551327
void visitRequirement(const Requirement &requirement, Label label) {
12561328
printHead("requirement", ASTNodeColor, label);
@@ -1262,13 +1334,19 @@ namespace {
12621334

12631335
printField(requirement.getKind(), Label::optional("kind"));
12641336

1265-
if (requirement.getKind() != RequirementKind::Layout
1266-
&& requirement.getSecondType())
1267-
printTypeField(requirement.getSecondType(),
1268-
Label::optional("second_type"), opts);
1269-
else if (requirement.getLayoutConstraint())
1337+
switch (requirement.getKind()) {
1338+
case RequirementKind::Layout:
12701339
printFieldQuoted(requirement.getLayoutConstraint(),
12711340
Label::optional("layout"));
1341+
break;
1342+
case RequirementKind::Conformance:
1343+
printReferencedDeclField(requirement.getProtocolDecl(),
1344+
Label::optional("protocol"));
1345+
break;
1346+
default:
1347+
printTypeField(requirement.getSecondType(),
1348+
Label::optional("second_type"), opts);
1349+
}
12721350

12731351
printFoot();
12741352
}
@@ -1917,6 +1995,62 @@ namespace {
19171995
}
19181996
}
19191997

1998+
void printInheritance(const IterableDeclContext *DC) {
1999+
if (!(Writer.isParsable() && isTypeChecked())) {
2000+
// If the output is not parsable or we're not type-checked, just print
2001+
// the inheritance list as written.
2002+
switch (DC->getIterableContextKind()) {
2003+
case IterableDeclContextKind::NominalTypeDecl:
2004+
printInherited(cast<NominalTypeDecl>(DC)->getInherited());
2005+
break;
2006+
case IterableDeclContextKind::ExtensionDecl:
2007+
printInherited(cast<ExtensionDecl>(DC)->getInherited());
2008+
break;
2009+
}
2010+
return;
2011+
}
2012+
2013+
// For parsable, type-checked output, print a more structured
2014+
// representation of the data.
2015+
printRecArbitrary(
2016+
[&](Label label) {
2017+
printHead("inheritance", FieldLabelColor, label);
2018+
2019+
SmallPtrSet<const ProtocolConformance *, 4> dumped;
2020+
printList(
2021+
DC->getLocalConformances(),
2022+
[&](auto conformance, Label label) {
2023+
printRec(conformance, dumped, label);
2024+
},
2025+
Label::always("conformances"));
2026+
2027+
if (auto CD = dyn_cast<ClassDecl>(DC); CD && CD->hasSuperclass()) {
2028+
printTypeField(CD->getSuperclass(),
2029+
Label::always("superclass_type"));
2030+
}
2031+
2032+
if (auto ED = dyn_cast<EnumDecl>(DC); ED && ED->hasRawType()) {
2033+
printTypeField(ED->getRawType(), Label::always("raw_type"));
2034+
}
2035+
2036+
if (auto PD = dyn_cast<ProtocolDecl>(DC)) {
2037+
printList(
2038+
PD->getAllInheritedProtocols(),
2039+
[&](auto inherited, Label label) {
2040+
printReferencedDeclField(inherited, label);
2041+
},
2042+
Label::always("protocols"));
2043+
if (PD->hasSuperclass()) {
2044+
printReferencedDeclField(PD->getSuperclassDecl(),
2045+
Label::always("superclass_decl_usr"));
2046+
}
2047+
}
2048+
2049+
printFoot();
2050+
},
2051+
Label::always("inherits"));
2052+
}
2053+
19202054
void printInherited(InheritedTypes Inherited) {
19212055
if (Writer.isParsable()) {
19222056
printList(
@@ -2252,13 +2386,13 @@ namespace {
22522386
switch (IDC->getIterableContextKind()) {
22532387
case IterableDeclContextKind::NominalTypeDecl: {
22542388
const auto NTD = cast<NominalTypeDecl>(IDC);
2255-
printInherited(NTD->getInherited());
2389+
printInheritance(NTD);
22562390
printWhereRequirements(NTD);
22572391
break;
22582392
}
22592393
case IterableDeclContextKind::ExtensionDecl:
22602394
const auto ED = cast<ExtensionDecl>(IDC);
2261-
printInherited(ED->getInherited());
2395+
printInheritance(ED);
22622396
printWhereRequirements(ED);
22632397
break;
22642398
}
@@ -2289,6 +2423,27 @@ namespace {
22892423
printFoot();
22902424
}
22912425

2426+
// Prints a mapping from the declared interface types of the opaque types to
2427+
// their equivalent existential type. This loses some information, but it is
2428+
// meant to make it easier to determine which protocols an opaque type
2429+
// conforms to when such a type appears elsewhere in an expression dump,
2430+
// farther away from where the opaque type is declared.
2431+
void printOpaqueTypeMapping(ArrayRef<OpaqueTypeDecl *> opaqueDecls) {
2432+
printRecArbitrary(
2433+
[&](Label label) {
2434+
printHead("opaque_to_existential_mapping", FieldLabelColor, label);
2435+
for (const auto OTD : opaqueDecls) {
2436+
Type interfaceType = OTD->getDeclaredInterfaceType();
2437+
Type existentialType =
2438+
replaceOpaqueArchetypesWithExistentials(interfaceType);
2439+
printTypeField(existentialType,
2440+
Label::always(typeUSR(interfaceType)));
2441+
}
2442+
printFoot();
2443+
},
2444+
Label::always("opaque_to_existential_mapping"));
2445+
}
2446+
22922447
void visitSourceFile(const SourceFile &SF) {
22932448
Writer.setMainBufferID(SF.getBufferID());
22942449

@@ -2357,6 +2512,15 @@ namespace {
23572512
}
23582513
},
23592514
Label::optional("items"));
2515+
2516+
if (Writer.isParsable() && isTypeChecked()) {
2517+
SmallVector<OpaqueTypeDecl *, 4> opaqueDecls;
2518+
SF.getOpaqueReturnTypeDecls(opaqueDecls);
2519+
if (!opaqueDecls.empty()) {
2520+
printOpaqueTypeMapping(opaqueDecls);
2521+
}
2522+
}
2523+
23602524
printFoot();
23612525
}
23622526

@@ -3941,36 +4105,7 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, Label>,
39414105

39424106
printField(E->getRawDiscriminator(), Label::always("discriminator"),
39434107
DiscriminatorColor);
3944-
3945-
switch (auto isolation = E->getActorIsolation()) {
3946-
case ActorIsolation::Unspecified:
3947-
case ActorIsolation::NonisolatedUnsafe:
3948-
break;
3949-
3950-
case ActorIsolation::Nonisolated:
3951-
printFlag(true, "nonisolated", CapturesColor);
3952-
break;
3953-
3954-
case ActorIsolation::Erased:
3955-
printFlag(true, "dynamically_isolated", CapturesColor);
3956-
break;
3957-
3958-
case ActorIsolation::CallerIsolationInheriting:
3959-
printFlag(true, "isolated_to_caller_isolation", CapturesColor);
3960-
break;
3961-
3962-
case ActorIsolation::ActorInstance:
3963-
printReferencedDeclWithContextField(isolation.getActorInstance(),
3964-
Label::always("actor_isolated"),
3965-
CapturesColor);
3966-
break;
3967-
3968-
case ActorIsolation::GlobalActor:
3969-
printTypeField(isolation.getGlobalActor(),
3970-
Label::always("global_actor_isolated"), PrintOptions(),
3971-
CapturesColor);
3972-
break;
3973-
}
4108+
printIsolation(E->getActorIsolation());
39744109

39754110
if (auto captureInfo = E->getCachedCaptureInfo()) {
39764111
printCaptureInfoField(captureInfo, Label::optional("captures"));
@@ -5552,6 +5687,9 @@ class PrintConformance : public PrintBase {
55525687
printTypeField(conformance->getType(), Label::always("type"));
55535688
printReferencedDeclField(conformance->getProtocol(),
55545689
Label::always("protocol"));
5690+
printField(conformance->getSourceKind(), Label::optional("source_kind"));
5691+
printFlag(conformance->isRetroactive(), "retroactive");
5692+
printIsolation(conformance->getIsolation());
55555693
if (!Writer.isParsable())
55565694
printFlag(!shouldPrintDetails, "<details printed above>");
55575695
};
@@ -5561,6 +5699,16 @@ class PrintConformance : public PrintBase {
55615699
auto normal = cast<NormalProtocolConformance>(conformance);
55625700

55635701
printCommon("normal_conformance");
5702+
printFlag(normal->isPreconcurrency(), "preconcurrency");
5703+
if (normal->isPreconcurrency() && normal->isComplete()) {
5704+
printFlag(normal->isPreconcurrencyEffectful(),
5705+
"effectful_preconcurrency");
5706+
}
5707+
printFlag(normal->isRetroactive(), "retroactive");
5708+
printFlag(normal->isUnchecked(), "unchecked");
5709+
if (normal->getExplicitSafety() != ExplicitSafety::Unspecified)
5710+
printField(normal->getExplicitSafety(), Label::always("safety"));
5711+
55645712
if (!shouldPrintDetails)
55655713
break;
55665714

@@ -5775,27 +5923,33 @@ class PrintConformance : public PrintBase {
57755923

57765924
void PrintBase::printRec(SubstitutionMap map, VisitedConformances &visited,
57775925
Label label) {
5778-
printRecArbitrary([&](Label label) {
5779-
PrintConformance(Writer)
5780-
.visitSubstitutionMap(map, SubstitutionMap::DumpStyle::Full, visited,
5781-
label);
5782-
}, label);
5926+
printRecArbitrary(
5927+
[&](Label label) {
5928+
PrintConformance(Writer, MemberLoading)
5929+
.visitSubstitutionMap(map, SubstitutionMap::DumpStyle::Full,
5930+
visited, label);
5931+
},
5932+
label);
57835933
}
57845934

57855935
void PrintBase::printRec(const ProtocolConformanceRef &ref,
57865936
VisitedConformances &visited, Label label) {
5787-
printRecArbitrary([&](Label label) {
5788-
PrintConformance(Writer)
5789-
.visitProtocolConformanceRef(ref, visited, label);
5790-
}, label);
5937+
printRecArbitrary(
5938+
[&](Label label) {
5939+
PrintConformance(Writer, MemberLoading)
5940+
.visitProtocolConformanceRef(ref, visited, label);
5941+
},
5942+
label);
57915943
}
57925944

57935945
void PrintBase::printRec(const ProtocolConformance *conformance,
57945946
VisitedConformances &visited, Label label) {
5795-
printRecArbitrary([&](Label label) {
5796-
PrintConformance(Writer)
5797-
.visitProtocolConformance(conformance, visited, label);
5798-
}, label);
5947+
printRecArbitrary(
5948+
[&](Label label) {
5949+
PrintConformance(Writer, MemberLoading)
5950+
.visitProtocolConformance(conformance, visited, label);
5951+
},
5952+
label);
57995953
}
58005954

58015955
} // end anonymous namespace

0 commit comments

Comments
 (0)