Skip to content

Commit 9e08b40

Browse files
committed
Mangler: Fix substitution ordering when mangling opaque return types.
When a declaration has a structural opaque return type like: func foo() -> Bar<some P> then to mangle that return type `Bar<some P>`, we have to mangle the `some P` part by referencing its defining declaration `foo()`, which in turn includes its return type `Bar<some P>` again (this time using a special mangling for `some P` that prevents infinite recursion). Since we mangle `Bar<some P>` once as part of mangling the declaration, and we register substitutions for bound generic types when they're complete, we end up registering the substitution for `Bar<some P>` twice, once as the return type of the declaration name, and again as the actual type. This would be fine, except that the mangler doesn't check for key collisions, and it picks substitution indexes based on the number of entries in its hash map, so the duplicated substitution ends up corrupting the substitution sequence, causing the mangler to produce an invalid mangled name. Fixing that exposes us to another problem in the remangler: the AST mangler keys substitutions by type identity, but the remangler uses the value of the demangled nodes to recognize substitutions. The mangling for `Bar<current declaration's opaque return type>` can appear multiple times in a demangled tree, but referring to different declarations' opaque return types, and the remangler would reconstruct an incorrect mangled name when this happens. To avoid this, change the way the demangler represents `OpaqueReturnType` nodes so that they contain a backreference to the declaration they represent, so that substitutions involving different declarations' opaque return types don't get confused.
1 parent 7497aee commit 9e08b40

File tree

11 files changed

+134
-26
lines changed

11 files changed

+134
-26
lines changed

include/swift/Basic/Mangler.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ class Mangler {
5454

5555
/// Identifier substitutions.
5656
llvm::StringMap<unsigned> StringSubstitutions;
57+
58+
/// Index to use for the next added substitution.
59+
/// Note that this is not simply the sum of the size of the \c Substitutions
60+
/// and \c StringSubstitutions maps above, since in some circumstances the
61+
/// same entity may be registered for multiple substitution indexes.
62+
unsigned NextSubstitutionIndex = 0;
5763

5864
/// Word substitutions in mangled identifiers.
5965
llvm::SmallVector<SubstitutionWord, 26> Words;
@@ -102,7 +108,6 @@ class Mangler {
102108
}
103109

104110
protected:
105-
106111
Mangler() : Buffer(Storage) { }
107112

108113
/// Begins a new mangling but does not add the mangling prefix.
@@ -134,15 +139,15 @@ class Mangler {
134139
void addSubstitution(const void *ptr) {
135140
if (!UseSubstitutions)
136141
return;
137-
138-
auto value = Substitutions.size() + StringSubstitutions.size();
142+
143+
auto value = NextSubstitutionIndex++;
139144
Substitutions[ptr] = value;
140145
}
141146
void addSubstitution(StringRef Str) {
142147
if (!UseSubstitutions)
143148
return;
144149

145-
auto value = Substitutions.size() + StringSubstitutions.size();
150+
auto value = NextSubstitutionIndex++;
146151
StringSubstitutions[Str] = value;
147152
}
148153

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ NODE(AccessibleFunctionRecord)
339339
NODE(CompileTimeConst)
340340

341341
// Added in Swift 5.7
342-
NODE(OpaqueReturnTypeIndexed)
343342
NODE(BackDeploymentThunk)
344343
NODE(BackDeploymentFallback)
345344
NODE(ExtendedExistentialTypeShape)
@@ -351,6 +350,8 @@ NODE(SymbolicExtendedExistentialType)
351350
// Added in Swift 5.8
352351
NODE(MetatypeParamsRemoved)
353352
NODE(HasSymbolQuery)
353+
NODE(OpaqueReturnTypeIndex)
354+
NODE(OpaqueReturnTypeParent)
354355

355356
#undef CONTEXT_NODE
356357
#undef NODE

include/swift/Demangling/Demangler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,9 @@ class Demangler : public NodeFactory {
475475
friend DemangleInitRAII;
476476

477477
void addSubstitution(NodePointer Nd) {
478-
if (Nd)
478+
if (Nd) {
479479
Substitutions.push_back(Nd, *this);
480+
}
480481
}
481482

482483
NodePointer addChild(NodePointer Parent, NodePointer Child);

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3237,7 +3237,7 @@ void ASTMangler::appendDeclType(const ValueDecl *decl,
32373237
} else {
32383238
appendType(type, sig, decl);
32393239
}
3240-
3240+
32413241
// Mangle the generic signature, if any.
32423242
if (genericSig && appendGenericSignature(genericSig, parentGenericSig)) {
32433243
// The 'F' function mangling doesn't need a 'u' for its generic signature.

lib/Basic/Mangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ void Mangler::beginManglingWithoutPrefix() {
114114
Storage.clear();
115115
Substitutions.clear();
116116
StringSubstitutions.clear();
117+
NextSubstitutionIndex = 0;
117118
Words.clear();
118119
SubstMerging.clear();
119120
}

lib/Demangling/Demangler.cpp

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,39 @@ NodePointer Demangler::demangleExtensionContext() {
13281328
return Ext;
13291329
}
13301330

1331+
/// Associate any \c OpaqueReturnType nodes with the declaration whose opaque
1332+
/// return type they refer back to.
1333+
static Node *setParentForOpaqueReturnTypeNodes(Demangler &D,
1334+
Node *parent,
1335+
Node *visitedNode) {
1336+
if (!parent || !visitedNode)
1337+
return nullptr;
1338+
if (visitedNode->getKind() == Node::Kind::OpaqueReturnType) {
1339+
// If this node is not already parented, parent it.
1340+
if (visitedNode->hasChildren()
1341+
&& visitedNode->getLastChild()->getKind() == Node::Kind::OpaqueReturnTypeParent) {
1342+
return parent;
1343+
}
1344+
visitedNode->addChild(D.createNode(Node::Kind::OpaqueReturnTypeParent,
1345+
(Node::IndexType)parent), D);
1346+
return parent;
1347+
}
1348+
1349+
// If this node is one that may in turn define its own opaque return type,
1350+
// stop recursion, since any opaque return type nodes underneath would refer
1351+
// to the nested declaration rather than the one we're looking at.
1352+
if (visitedNode->getKind() == Node::Kind::Function
1353+
|| visitedNode->getKind() == Node::Kind::Variable
1354+
|| visitedNode->getKind() == Node::Kind::Subscript) {
1355+
return parent;
1356+
}
1357+
1358+
for (size_t i = 0, e = visitedNode->getNumChildren(); i < e; ++i) {
1359+
setParentForOpaqueReturnTypeNodes(D, parent, visitedNode->getChild(i));
1360+
}
1361+
return parent;
1362+
}
1363+
13311364
NodePointer Demangler::demanglePlainFunction() {
13321365
NodePointer GenSig = popNode(Node::Kind::DependentGenericSignature);
13331366
NodePointer Type = popFunctionType(Node::Kind::FunctionType);
@@ -1341,10 +1374,12 @@ NodePointer Demangler::demanglePlainFunction() {
13411374
auto Name = popNode(isDeclName);
13421375
auto Ctx = popContext();
13431376

1344-
if (LabelList)
1345-
return createWithChildren(Node::Kind::Function, Ctx, Name, LabelList, Type);
1346-
1347-
return createWithChildren(Node::Kind::Function, Ctx, Name, Type);
1377+
NodePointer result = LabelList
1378+
? createWithChildren(Node::Kind::Function, Ctx, Name, LabelList, Type)
1379+
: createWithChildren(Node::Kind::Function, Ctx, Name, Type);
1380+
1381+
result = setParentForOpaqueReturnTypeNodes(*this, result, Type);
1382+
return result;
13481383
}
13491384

13501385
NodePointer Demangler::popFunctionType(Node::Kind kind, bool hasClangType) {
@@ -2270,7 +2305,8 @@ NodePointer Demangler::demangleArchetype() {
22702305
int ordinal = demangleIndex();
22712306
if (ordinal < 0)
22722307
return NULL;
2273-
return createType(createNode(Node::Kind::OpaqueReturnTypeIndexed, ordinal));
2308+
return createType(createWithChild(Node::Kind::OpaqueReturnType,
2309+
createNode(Node::Kind::OpaqueReturnTypeIndex, ordinal)));
22742310
}
22752311

22762312
case 'x': {
@@ -3360,7 +3396,7 @@ NodePointer Demangler::demangleSpecialType() {
33603396
return nullptr;
33613397
// Build layout.
33623398
auto layout = createNode(Node::Kind::SILBoxLayout);
3363-
for (unsigned i = 0, e = fieldTypes->getNumChildren(); i < e; ++i) {
3399+
for (size_t i = 0, e = fieldTypes->getNumChildren(); i < e; ++i) {
33643400
auto fieldType = fieldTypes->getChild(i);
33653401
assert(fieldType->getKind() == Node::Kind::Type);
33663402
bool isMutable = false;
@@ -3600,8 +3636,11 @@ NodePointer Demangler::demangleEntity(Node::Kind Kind) {
36003636
NodePointer LabelList = popFunctionParamLabels(Type);
36013637
NodePointer Name = popNode(isDeclName);
36023638
NodePointer Context = popContext();
3603-
return LabelList ? createWithChildren(Kind, Context, Name, LabelList, Type)
3604-
: createWithChildren(Kind, Context, Name, Type);
3639+
auto result = LabelList ? createWithChildren(Kind, Context, Name, LabelList, Type)
3640+
: createWithChildren(Kind, Context, Name, Type);
3641+
3642+
result = setParentForOpaqueReturnTypeNodes(*this, result, Type);
3643+
return result;
36053644
}
36063645

36073646
NodePointer Demangler::demangleVariable() {
@@ -3623,6 +3662,8 @@ NodePointer Demangler::demangleSubscript() {
36233662
addChild(Subscript, LabelList);
36243663
Subscript = addChild(Subscript, Type);
36253664
addChild(Subscript, PrivateName);
3665+
3666+
Subscript = setParentForOpaqueReturnTypeNodes(*this, Subscript, Type);
36263667

36273668
return demangleAccessor(Subscript);
36283669
}

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,8 @@ class NodePrinter {
579579
case Node::Kind::OpaqueType:
580580
case Node::Kind::OpaqueTypeDescriptorSymbolicReference:
581581
case Node::Kind::OpaqueReturnType:
582-
case Node::Kind::OpaqueReturnTypeIndexed:
582+
case Node::Kind::OpaqueReturnTypeIndex:
583+
case Node::Kind::OpaqueReturnTypeParent:
583584
case Node::Kind::OpaqueReturnTypeOf:
584585
case Node::Kind::CanonicalSpecializedGenericMetaclass:
585586
case Node::Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
@@ -2915,7 +2916,6 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
29152916
Printer << ")";
29162917
return nullptr;
29172918
case Node::Kind::OpaqueReturnType:
2918-
case Node::Kind::OpaqueReturnTypeIndexed:
29192919
Printer << "some";
29202920
return nullptr;
29212921
case Node::Kind::OpaqueReturnTypeOf:
@@ -3080,6 +3080,9 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
30803080
case Node::Kind::HasSymbolQuery:
30813081
Printer << "#_hasSymbol query for ";
30823082
return nullptr;
3083+
case Node::Kind::OpaqueReturnTypeIndex:
3084+
case Node::Kind::OpaqueReturnTypeParent:
3085+
return nullptr;
30833086
}
30843087

30853088
printer_unreachable("bad node kind!");

lib/Demangling/OldDemangler.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2089,7 +2089,10 @@ class OldDemangler {
20892089
Node::IndexType ordinal;
20902090
if (!demangleIndex(ordinal, depth))
20912091
return nullptr;
2092-
return Factory.createNode(Node::Kind::OpaqueReturnTypeIndexed, ordinal);
2092+
auto result = Factory.createNode(Node::Kind::OpaqueReturnType);
2093+
result->addChild(
2094+
Factory.createNode(Node::Kind::OpaqueReturnTypeIndex, ordinal), Factory);
2095+
return result;
20932096
}
20942097
return demangleArchetypeType(depth + 1);
20952098
}

lib/Demangling/OldRemangler.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,13 +2674,21 @@ ManglingError Remangler::mangleSugaredParen(Node *node, unsigned depth) {
26742674
}
26752675

26762676
ManglingError Remangler::mangleOpaqueReturnType(Node *node, unsigned depth) {
2677+
if (node->hasChildren()
2678+
&& node->getFirstChild()->getKind() == Node::Kind::OpaqueReturnTypeIndex){
2679+
Buffer << "QU";
2680+
mangleIndex(node->getFirstChild()->getIndex());
2681+
return ManglingError::Success;
2682+
}
2683+
26772684
Buffer << "Qu";
26782685
return ManglingError::Success;
26792686
}
2680-
ManglingError Remangler::mangleOpaqueReturnTypeIndexed(Node *node, unsigned depth) {
2681-
Buffer << "QU";
2682-
mangleIndex(node->getIndex());
2683-
return ManglingError::Success;
2687+
ManglingError Remangler::mangleOpaqueReturnTypeIndex(Node *node, unsigned depth) {
2688+
return ManglingError::WrongNodeType;
2689+
}
2690+
ManglingError Remangler::mangleOpaqueReturnTypeParent(Node *node, unsigned depth) {
2691+
return ManglingError::WrongNodeType;
26842692
}
26852693
ManglingError Remangler::mangleOpaqueReturnTypeOf(Node *node,
26862694
EntityContext &ctx,

lib/Demangling/Remangler.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3387,13 +3387,22 @@ ManglingError Remangler::mangleSugaredParen(Node *node, unsigned depth) {
33873387
}
33883388

33893389
ManglingError Remangler::mangleOpaqueReturnType(Node *node, unsigned depth) {
3390+
if (node->hasChildren()
3391+
&& node->getFirstChild()->getKind() == Node::Kind::OpaqueReturnTypeIndex) {
3392+
Buffer << "QR";
3393+
mangleIndex(node->getFirstChild()->getIndex());
3394+
return ManglingError::Success;
3395+
}
33903396
Buffer << "Qr";
33913397
return ManglingError::Success;
33923398
}
3393-
ManglingError Remangler::mangleOpaqueReturnTypeIndexed(Node *node, unsigned depth) {
3394-
Buffer << "QR";
3395-
mangleIndex(node->getIndex());
3396-
return ManglingError::Success;
3399+
ManglingError Remangler::mangleOpaqueReturnTypeIndex(Node *node, unsigned depth) {
3400+
// Cannot appear unparented to an OpaqueReturnType.
3401+
return ManglingError::WrongNodeType;
3402+
}
3403+
ManglingError Remangler::mangleOpaqueReturnTypeParent(Node *node, unsigned depth) {
3404+
// Cannot appear unparented to an OpaqueReturnType.
3405+
return ManglingError::WrongNodeType;
33973406
}
33983407
ManglingError Remangler::mangleOpaqueReturnTypeOf(Node *node, unsigned depth) {
33993408
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));

0 commit comments

Comments
 (0)