@@ -200,6 +200,33 @@ class escaping_ostream : public raw_ostream {
200
200
virtual void anchor () override {}
201
201
};
202
202
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
+
203
230
// / Returns the USR of the given declaration. Gracefully returns an empty
204
231
// / string if D is null or invalid.
205
232
std::string declUSR (const Decl *D) {
@@ -237,15 +264,7 @@ std::string typeUSR(Type type) {
237
264
type = type->mapTypeOutOfContext ();
238
265
}
239
266
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);
249
268
}
250
269
251
270
std::string usr;
@@ -1323,27 +1342,19 @@ namespace {
1323
1342
1324
1343
printField (requirement.getKind (), Label::optional (" kind" ));
1325
1344
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:
1345
1347
printFieldQuoted (requirement.getLayoutConstraint (),
1346
1348
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
+ }
1347
1358
1348
1359
printFoot ();
1349
1360
}
@@ -2022,8 +2033,8 @@ namespace {
2022
2033
Label::always (" conformances" ));
2023
2034
2024
2035
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 " ));
2027
2038
}
2028
2039
2029
2040
if (auto ED = dyn_cast<EnumDecl>(DC); ED && ED->hasRawType ()) {
@@ -2432,8 +2443,7 @@ namespace {
2432
2443
for (const auto OTD : opaqueDecls) {
2433
2444
Type interfaceType = OTD->getDeclaredInterfaceType ();
2434
2445
Type existentialType =
2435
- interfaceType->castTo <OpaqueTypeArchetypeType>()
2436
- ->getExistentialType ();
2446
+ replaceOpaqueArchetypesWithExistentials (interfaceType);
2437
2447
printTypeField (existentialType,
2438
2448
Label::always (typeUSR (interfaceType)));
2439
2449
}
0 commit comments