Skip to content

Commit 8ffa514

Browse files
committed
AST: Fix mangling for nested generic types
Change the 'G' mangling to include generic parameters from all levels of nested nominal types, and not just the innermost. Note that the raw mangling syntax is something like this for a nested type 'A<Int>.B<String>': - bound_generic - struct 'B' - struct 'A' - module 'M' - args - Int - args - String However, the actual mangling tree is more along the lines of: - bound_generic_struct 'B' - bound_generic_struct 'A' - module 'M' - args - Int - args - String This arrangement improves the quality of substitutions (we are more likely to have a substitution for the entire unbound generic type name 'A.B' around), and simplifies a few other details. Unfortunately, the remangling logic becomes slightly grotesque. A simple SILGen test for nested generics exercises the mangling, and ensures that Sema and SILGen do not crash with nested generics. More detailed SILGen tests, as well as IRGen support for nested generics is next.
1 parent 7e6ece6 commit 8ffa514

File tree

7 files changed

+471
-87
lines changed

7 files changed

+471
-87
lines changed

include/swift/AST/Mangle.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class Mangler {
9292
void mangleClosureEntity(const AbstractClosureExpr *closure,
9393
unsigned uncurryingLevel);
9494
void mangleNominalType(const NominalTypeDecl *decl);
95+
void mangleBoundGenericType(Type type);
9596
void mangleProtocolDecl(const ProtocolDecl *protocol);
9697
void mangleType(Type type, unsigned uncurryingLevel);
9798
void mangleDirectness(bool isIndirect);

lib/AST/Mangle.cpp

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -940,32 +940,17 @@ void Mangler::mangleType(Type type, unsigned uncurryLevel) {
940940
Buffer << '_';
941941
return;
942942

943-
case TypeKind::UnboundGeneric: {
944-
// We normally reject unbound types in IR-generation, but there
945-
// are several occasions in which we'd like to mangle them in the
946-
// abstract.
947-
auto decl = cast<UnboundGenericType>(tybase)->getDecl();
948-
mangleNominalType(cast<NominalTypeDecl>(decl));
949-
return;
950-
}
951-
943+
case TypeKind::UnboundGeneric:
952944
case TypeKind::Class:
953945
case TypeKind::Enum:
954-
case TypeKind::Struct: {
955-
return mangleNominalType(cast<NominalType>(tybase)->getDecl());
956-
}
957-
946+
case TypeKind::Struct:
958947
case TypeKind::BoundGenericClass:
959948
case TypeKind::BoundGenericEnum:
960949
case TypeKind::BoundGenericStruct: {
961-
// type ::= 'G' <type> <type>+ '_'
962-
auto *boundType = cast<BoundGenericType>(tybase);
963-
Buffer << 'G';
964-
mangleNominalType(boundType->getDecl());
965-
for (auto arg : boundType->getGenericArgs()) {
966-
mangleType(arg, /*uncurry*/ 0);
967-
}
968-
Buffer << '_';
950+
if (type->isSpecialized())
951+
mangleBoundGenericType(type);
952+
else
953+
mangleNominalType(tybase->getAnyNominal());
969954
return;
970955
}
971956

@@ -1332,6 +1317,46 @@ void Mangler::mangleNominalType(const NominalTypeDecl *decl) {
13321317
addSubstitution(key);
13331318
}
13341319

1320+
static void
1321+
collectBoundGenericArgs(Type type,
1322+
SmallVectorImpl<SmallVector<Type, 2>> &genericArgs) {
1323+
if (auto *unboundType = type->getAs<UnboundGenericType>()) {
1324+
if (auto parent = unboundType->getParent())
1325+
collectBoundGenericArgs(parent, genericArgs);
1326+
genericArgs.push_back({});
1327+
} else if (auto *nominalType = type->getAs<NominalType>()) {
1328+
if (auto parent = nominalType->getParent())
1329+
collectBoundGenericArgs(parent, genericArgs);
1330+
genericArgs.push_back({});
1331+
} else {
1332+
auto *boundType = type->castTo<BoundGenericType>();
1333+
if (auto parent = boundType->getParent())
1334+
collectBoundGenericArgs(parent, genericArgs);
1335+
1336+
SmallVector<Type, 2> args;
1337+
for (auto arg : boundType->getGenericArgs())
1338+
args.push_back(arg);
1339+
genericArgs.push_back(args);
1340+
}
1341+
}
1342+
1343+
void Mangler::mangleBoundGenericType(Type type) {
1344+
// type ::= 'G' <type> (<type>+ '_')+
1345+
Buffer << 'G';
1346+
auto *nominal = type->getAnyNominal();
1347+
mangleNominalType(nominal);
1348+
1349+
SmallVector<SmallVector<Type, 2>, 2> genericArgs;
1350+
collectBoundGenericArgs(type, genericArgs);
1351+
assert(!genericArgs.empty());
1352+
1353+
for (auto args : genericArgs) {
1354+
for (auto arg : args)
1355+
mangleType(arg, /*uncurry*/ 0);
1356+
Buffer << '_';
1357+
}
1358+
}
1359+
13351360
void Mangler::mangleProtocolDecl(const ProtocolDecl *protocol) {
13361361
Buffer << 'P';
13371362
mangleContextOf(protocol);

lib/Basic/Demangle.cpp

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,73 @@ class Demangler {
11541154
return nullptr;
11551155
}
11561156

1157+
NodePointer demangleBoundGenericArgs(NodePointer nominalType) {
1158+
// Generic arguments for the outermost type come first.
1159+
NodePointer parentOrModule = nominalType->getChild(0);
1160+
if (parentOrModule->getKind() != Node::Kind::Module) {
1161+
parentOrModule = demangleBoundGenericArgs(parentOrModule);
1162+
1163+
// Rebuild this type with the new parent type, which may have
1164+
// had its generic arguments applied.
1165+
NodePointer result = NodeFactory::create(nominalType->getKind());
1166+
result->addChild(parentOrModule);
1167+
result->addChild(nominalType->getChild(1));
1168+
1169+
nominalType = result;
1170+
}
1171+
1172+
NodePointer args = NodeFactory::create(Node::Kind::TypeList);
1173+
while (!Mangled.nextIf('_')) {
1174+
NodePointer type = demangleType();
1175+
if (!type)
1176+
return nullptr;
1177+
args->addChild(type);
1178+
if (Mangled.isEmpty())
1179+
return nullptr;
1180+
}
1181+
1182+
// If there were no arguments at this level there is nothing left
1183+
// to do.
1184+
if (args->getNumChildren() == 0)
1185+
return nominalType;
1186+
1187+
// Otherwise, build a bound generic type node from the unbound
1188+
// type and arguments.
1189+
NodePointer unboundType = NodeFactory::create(Node::Kind::Type);
1190+
unboundType->addChild(nominalType);
1191+
1192+
Node::Kind kind;
1193+
switch (nominalType->getKind()) { // look through Type node
1194+
case Node::Kind::Class:
1195+
kind = Node::Kind::BoundGenericClass;
1196+
break;
1197+
case Node::Kind::Structure:
1198+
kind = Node::Kind::BoundGenericStructure;
1199+
break;
1200+
case Node::Kind::Enum:
1201+
kind = Node::Kind::BoundGenericEnum;
1202+
break;
1203+
default:
1204+
return nullptr;
1205+
}
1206+
NodePointer result = NodeFactory::create(kind);
1207+
result->addChild(unboundType);
1208+
result->addChild(args);
1209+
return result;
1210+
}
1211+
1212+
NodePointer demangleBoundGenericType() {
1213+
// bound-generic-type ::= 'G' nominal-type (args+ '_')+
1214+
//
1215+
// Each level of nominal type nesting has its own list of arguments.
1216+
1217+
NodePointer nominalType = demangleNominalType();
1218+
if (!nominalType)
1219+
return nullptr;
1220+
1221+
return demangleBoundGenericArgs(nominalType);
1222+
}
1223+
11571224
NodePointer demangleContext() {
11581225
// context ::= module
11591226
// context ::= entity
@@ -1191,6 +1258,8 @@ class Demangler {
11911258
return demangleSubstitutionIndex();
11921259
if (Mangled.nextIf('s'))
11931260
return NodeFactory::create(Node::Kind::Module, STDLIB_NAME);
1261+
if (Mangled.nextIf('G'))
1262+
return demangleBoundGenericType();
11941263
if (isStartOfEntity(Mangled.peek()))
11951264
return demangleEntity();
11961265
return demangleModule();
@@ -1872,37 +1941,7 @@ class Demangler {
18721941
return demangleFunctionType(Node::Kind::UncurriedFunctionType);
18731942
}
18741943
if (c == 'G') {
1875-
NodePointer unboundType = demangleType();
1876-
if (!unboundType)
1877-
return nullptr;
1878-
NodePointer type_list = NodeFactory::create(Node::Kind::TypeList);
1879-
while (!Mangled.nextIf('_')) {
1880-
NodePointer type = demangleType();
1881-
if (!type)
1882-
return nullptr;
1883-
type_list->addChild(type);
1884-
if (Mangled.isEmpty())
1885-
return nullptr;
1886-
}
1887-
Node::Kind bound_type_kind;
1888-
switch (unboundType->getChild(0)->getKind()) { // look through Type node
1889-
case Node::Kind::Class:
1890-
bound_type_kind = Node::Kind::BoundGenericClass;
1891-
break;
1892-
case Node::Kind::Structure:
1893-
bound_type_kind = Node::Kind::BoundGenericStructure;
1894-
break;
1895-
case Node::Kind::Enum:
1896-
bound_type_kind = Node::Kind::BoundGenericEnum;
1897-
break;
1898-
default:
1899-
return nullptr;
1900-
}
1901-
NodePointer type_application =
1902-
NodeFactory::create(bound_type_kind);
1903-
type_application->addChild(unboundType);
1904-
type_application->addChild(type_list);
1905-
return type_application;
1944+
return demangleBoundGenericType();
19061945
}
19071946
if (c == 'X') {
19081947
if (Mangled.nextIf('b')) {
@@ -2049,10 +2088,8 @@ class Demangler {
20492088

20502089
return nullptr;
20512090
}
2052-
if (isStartOfNominalType(c)) {
2053-
NodePointer nominal_type = demangleDeclarationName(nominalTypeMarkerToNodeKind(c));
2054-
return nominal_type;
2055-
}
2091+
if (isStartOfNominalType(c))
2092+
return demangleDeclarationName(nominalTypeMarkerToNodeKind(c));
20562093
return nullptr;
20572094
}
20582095

0 commit comments

Comments
 (0)