Skip to content

Commit 6263956

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 77527c9 commit 6263956

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)
@@ -353,6 +352,8 @@ NODE(MetatypeParamsRemoved)
353352
NODE(HasSymbolQuery)
354353
NODE(RuntimeDiscoverableAttributeRecord)
355354
CONTEXT_NODE(RuntimeAttributeGenerator)
355+
NODE(OpaqueReturnTypeIndex)
356+
NODE(OpaqueReturnTypeParent)
356357

357358
#undef CONTEXT_NODE
358359
#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
@@ -3247,7 +3247,7 @@ void ASTMangler::appendDeclType(const ValueDecl *decl,
32473247
} else {
32483248
appendType(type, sig, decl);
32493249
}
3250-
3250+
32513251
// Mangle the generic signature, if any.
32523252
if (genericSig && appendGenericSignature(genericSig, parentGenericSig)) {
32533253
// 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
@@ -1330,6 +1330,39 @@ NodePointer Demangler::demangleExtensionContext() {
13301330
return Ext;
13311331
}
13321332

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

1346-
if (LabelList)
1347-
return createWithChildren(Node::Kind::Function, Ctx, Name, LabelList, Type);
1348-
1349-
return createWithChildren(Node::Kind::Function, Ctx, Name, Type);
1379+
NodePointer result = LabelList
1380+
? createWithChildren(Node::Kind::Function, Ctx, Name, LabelList, Type)
1381+
: createWithChildren(Node::Kind::Function, Ctx, Name, Type);
1382+
1383+
result = setParentForOpaqueReturnTypeNodes(*this, result, Type);
1384+
return result;
13501385
}
13511386

13521387
NodePointer Demangler::popFunctionType(Node::Kind kind, bool hasClangType) {
@@ -2273,7 +2308,8 @@ NodePointer Demangler::demangleArchetype() {
22732308
int ordinal = demangleIndex();
22742309
if (ordinal < 0)
22752310
return NULL;
2276-
return createType(createNode(Node::Kind::OpaqueReturnTypeIndexed, ordinal));
2311+
return createType(createWithChild(Node::Kind::OpaqueReturnType,
2312+
createNode(Node::Kind::OpaqueReturnTypeIndex, ordinal)));
22772313
}
22782314

22792315
case 'x': {
@@ -3363,7 +3399,7 @@ NodePointer Demangler::demangleSpecialType() {
33633399
return nullptr;
33643400
// Build layout.
33653401
auto layout = createNode(Node::Kind::SILBoxLayout);
3366-
for (unsigned i = 0, e = fieldTypes->getNumChildren(); i < e; ++i) {
3402+
for (size_t i = 0, e = fieldTypes->getNumChildren(); i < e; ++i) {
33673403
auto fieldType = fieldTypes->getChild(i);
33683404
assert(fieldType->getKind() == Node::Kind::Type);
33693405
bool isMutable = false;
@@ -3617,8 +3653,11 @@ NodePointer Demangler::demangleEntity(Node::Kind Kind) {
36173653
NodePointer LabelList = popFunctionParamLabels(Type);
36183654
NodePointer Name = popNode(isDeclName);
36193655
NodePointer Context = popContext();
3620-
return LabelList ? createWithChildren(Kind, Context, Name, LabelList, Type)
3621-
: createWithChildren(Kind, Context, Name, Type);
3656+
auto result = LabelList ? createWithChildren(Kind, Context, Name, LabelList, Type)
3657+
: createWithChildren(Kind, Context, Name, Type);
3658+
3659+
result = setParentForOpaqueReturnTypeNodes(*this, result, Type);
3660+
return result;
36223661
}
36233662

36243663
NodePointer Demangler::demangleVariable() {
@@ -3640,6 +3679,8 @@ NodePointer Demangler::demangleSubscript() {
36403679
addChild(Subscript, LabelList);
36413680
Subscript = addChild(Subscript, Type);
36423681
addChild(Subscript, PrivateName);
3682+
3683+
Subscript = setParentForOpaqueReturnTypeNodes(*this, Subscript, Type);
36433684

36443685
return demangleAccessor(Subscript);
36453686
}

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:
@@ -2922,7 +2923,6 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
29222923
Printer << ")";
29232924
return nullptr;
29242925
case Node::Kind::OpaqueReturnType:
2925-
case Node::Kind::OpaqueReturnTypeIndexed:
29262926
Printer << "some";
29272927
return nullptr;
29282928
case Node::Kind::OpaqueReturnTypeOf:
@@ -3094,6 +3094,9 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
30943094
Printer << " for attribute = " << Node->getChild(1)->getText() << "."
30953095
<< Node->getChild(2)->getText();
30963096
return nullptr;
3097+
case Node::Kind::OpaqueReturnTypeIndex:
3098+
case Node::Kind::OpaqueReturnTypeParent:
3099+
return nullptr;
30973100
}
30983101

30993102
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
@@ -3389,13 +3389,22 @@ ManglingError Remangler::mangleSugaredParen(Node *node, unsigned depth) {
33893389
}
33903390

33913391
ManglingError Remangler::mangleOpaqueReturnType(Node *node, unsigned depth) {
3392+
if (node->hasChildren()
3393+
&& node->getFirstChild()->getKind() == Node::Kind::OpaqueReturnTypeIndex) {
3394+
Buffer << "QR";
3395+
mangleIndex(node->getFirstChild()->getIndex());
3396+
return ManglingError::Success;
3397+
}
33923398
Buffer << "Qr";
33933399
return ManglingError::Success;
33943400
}
3395-
ManglingError Remangler::mangleOpaqueReturnTypeIndexed(Node *node, unsigned depth) {
3396-
Buffer << "QR";
3397-
mangleIndex(node->getIndex());
3398-
return ManglingError::Success;
3401+
ManglingError Remangler::mangleOpaqueReturnTypeIndex(Node *node, unsigned depth) {
3402+
// Cannot appear unparented to an OpaqueReturnType.
3403+
return ManglingError::WrongNodeType;
3404+
}
3405+
ManglingError Remangler::mangleOpaqueReturnTypeParent(Node *node, unsigned depth) {
3406+
// Cannot appear unparented to an OpaqueReturnType.
3407+
return ManglingError::WrongNodeType;
33993408
}
34003409
ManglingError Remangler::mangleOpaqueReturnTypeOf(Node *node, unsigned depth) {
34013410
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));

0 commit comments

Comments
 (0)