Skip to content

Commit 592398f

Browse files
authored
Merge pull request #81069 from allevato/6.2-json-ast-fixes
[🍒 6.2] [AST] More JSON AST dump improvements.
2 parents 9f4ce07 + 8ca0b41 commit 592398f

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"));
@@ -5551,6 +5686,9 @@ class PrintConformance : public PrintBase {
55515686
printTypeField(conformance->getType(), Label::always("type"));
55525687
printReferencedDeclField(conformance->getProtocol(),
55535688
Label::always("protocol"));
5689+
printField(conformance->getSourceKind(), Label::optional("source_kind"));
5690+
printFlag(conformance->isRetroactive(), "retroactive");
5691+
printIsolation(conformance->getIsolation());
55545692
if (!Writer.isParsable())
55555693
printFlag(!shouldPrintDetails, "<details printed above>");
55565694
};
@@ -5560,6 +5698,16 @@ class PrintConformance : public PrintBase {
55605698
auto normal = cast<NormalProtocolConformance>(conformance);
55615699

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

@@ -5774,27 +5922,33 @@ class PrintConformance : public PrintBase {
57745922

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

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

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

58005954
} // end anonymous namespace

0 commit comments

Comments
 (0)