Skip to content

Commit 5be2498

Browse files
committed
Address review feedback.
1 parent ef6352c commit 5be2498

File tree

2 files changed

+49
-32
lines changed

2 files changed

+49
-32
lines changed

lib/AST/ASTDumper.cpp

Lines changed: 42 additions & 32 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) {
@@ -237,15 +264,7 @@ std::string typeUSR(Type type) {
237264
type = type->mapTypeOutOfContext();
238265
}
239266
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.
243-
type = type.transformRec([&](TypeBase *t) -> std::optional<Type> {
244-
if (auto LAT = dyn_cast<LocalArchetypeType>(t)) {
245-
return LAT->getExistentialType();
246-
}
247-
return std::nullopt;
248-
});
267+
type = replaceLocalArchetypesWithExistentials(type);
249268
}
250269

251270
std::string usr;
@@ -1323,27 +1342,19 @@ namespace {
13231342

13241343
printField(requirement.getKind(), Label::optional("kind"));
13251344

1326-
if (requirement.getKind() != RequirementKind::Layout &&
1327-
requirement.getSecondType()) {
1328-
if (Writer.isParsable()) {
1329-
// If this is a conformance requirement, print the USR of the protocol
1330-
// decl instead of the type. The type USR for a protocol is based on
1331-
// the equivalent expanded existential, which drops suppressed
1332-
// protocols.
1333-
if (requirement.getKind() == RequirementKind::Conformance) {
1334-
printReferencedDeclField(requirement.getProtocolDecl(),
1335-
Label::optional("protocol"));
1336-
} else {
1337-
printTypeField(requirement.getSecondType(),
1338-
Label::optional("second_type"), opts);
1339-
}
1340-
} else {
1341-
printTypeField(requirement.getSecondType(),
1342-
Label::optional("second_type"), opts);
1343-
}
1344-
} else if (requirement.getLayoutConstraint())
1345+
switch (requirement.getKind()) {
1346+
case RequirementKind::Layout:
13451347
printFieldQuoted(requirement.getLayoutConstraint(),
13461348
Label::optional("layout"));
1349+
break;
1350+
case RequirementKind::Conformance:
1351+
printReferencedDeclField(requirement.getProtocolDecl(),
1352+
Label::optional("protocol"));
1353+
break;
1354+
default:
1355+
printTypeField(requirement.getSecondType(),
1356+
Label::optional("second_type"), opts);
1357+
}
13471358

13481359
printFoot();
13491360
}
@@ -2022,8 +2033,8 @@ namespace {
20222033
Label::always("conformances"));
20232034

20242035
if (auto CD = dyn_cast<ClassDecl>(DC); CD && CD->hasSuperclass()) {
2025-
printReferencedDeclField(CD->getSuperclassDecl(),
2026-
Label::always("superclass_decl_usr"));
2036+
printTypeField(CD->getSuperclass(),
2037+
Label::always("superclass_type"));
20272038
}
20282039

20292040
if (auto ED = dyn_cast<EnumDecl>(DC); ED && ED->hasRawType()) {
@@ -2432,8 +2443,7 @@ namespace {
24322443
for (const auto OTD : opaqueDecls) {
24332444
Type interfaceType = OTD->getDeclaredInterfaceType();
24342445
Type existentialType =
2435-
interfaceType->castTo<OpaqueTypeArchetypeType>()
2436-
->getExistentialType();
2446+
replaceOpaqueArchetypesWithExistentials(interfaceType);
24372447
printTypeField(existentialType,
24382448
Label::always(typeUSR(interfaceType)));
24392449
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,13 @@ func sb3() {
263263
}
264264
}
265265

266+
func nestedOpaques0() -> some BinaryInteger { 2 }
267+
func nestedOpaques1() -> some FixedWidthInteger & SignedInteger { 2 }
268+
func nestedOpaques2() -> (some BinaryInteger, some Sequence) { (2, []) }
269+
func nestedOpaques3() -> (some BinaryInteger, some Sequence<Double>) { (2, []) }
270+
func nestedOpaques4() -> (some BinaryInteger)? { Bool.random() ? 2 : nil }
271+
func nestedOpaques5() -> [some BinaryInteger] { [2] }
272+
266273
// Expressions
267274

268275
func zz1() throws {

0 commit comments

Comments
 (0)