Skip to content

Commit 9b0a94f

Browse files
authored
Merge pull request #22200 from slavapestov/fix-remangler
Remangler round-tripping fixes
2 parents 68ba134 + 0882695 commit 9b0a94f

File tree

8 files changed

+173
-72
lines changed

8 files changed

+173
-72
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ class ASTMangler : public Mangler {
7676
ASTMangler(bool DWARFMangling = false)
7777
: DWARFMangling(DWARFMangling) {}
7878

79+
void addTypeSubstitution(Type type) {
80+
type = dropProtocolsFromAssociatedTypes(type);
81+
addSubstitution(type.getPointer());
82+
}
83+
bool tryMangleTypeSubstitution(Type type) {
84+
type = dropProtocolsFromAssociatedTypes(type);
85+
return tryMangleSubstitution(type.getPointer());
86+
}
87+
7988
std::string mangleClosureEntity(const AbstractClosureExpr *closure,
8089
SymbolKind SKind);
8190

@@ -261,6 +270,9 @@ class ASTMangler : public Mangler {
261270
unsigned initialParamDepth,
262271
ArrayRef<Requirement> requirements);
263272

273+
DependentMemberType *dropProtocolFromAssociatedType(DependentMemberType *dmt);
274+
Type dropProtocolsFromAssociatedTypes(Type type);
275+
264276
void appendAssociatedTypeName(DependentMemberType *dmt);
265277

266278
void appendClosureEntity(const SerializedAbstractClosureExpr *closure);

include/swift/Demangling/Demangle.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,10 @@ const char *getNodeKindString(swift::Demangle::Node::Kind k);
564564
/// Useful for debugging.
565565
std::string getNodeTreeAsString(NodePointer Root);
566566

567+
bool nodeConsumesGenericArgs(Node *node);
568+
567569
bool isSpecialized(Node *node);
570+
568571
NodePointer getUnspecialized(Node *node, NodeFactory &Factory);
569572
std::string archetypeName(Node::IndexType index, Node::IndexType depth);
570573

lib/AST/ASTMangler.cpp

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -737,15 +737,15 @@ void ASTMangler::appendType(Type type) {
737737

738738
if (aliasTy->getSubstitutionMap().hasAnySubstitutableParams()) {
739739
// Try to mangle the entire name as a substitution.
740-
if (tryMangleSubstitution(tybase))
740+
if (tryMangleTypeSubstitution(tybase))
741741
return;
742742

743743
appendAnyGenericType(decl);
744744
bool isFirstArgList = true;
745745
appendBoundGenericArgs(type, isFirstArgList);
746746
appendRetroactiveConformances(type);
747747
appendOperator("G");
748-
addSubstitution(type.getPointer());
748+
addTypeSubstitution(type);
749749
return;
750750
}
751751

@@ -840,7 +840,7 @@ void ASTMangler::appendType(Type type) {
840840
Decl = type->getAnyGeneric();
841841
if (shouldMangleAsGeneric(type)) {
842842
// Try to mangle the entire name as a substitution.
843-
if (tryMangleSubstitution(tybase))
843+
if (tryMangleTypeSubstitution(tybase))
844844
return;
845845

846846
if (isStdlibType(Decl) && Decl->getName().str() == "Optional") {
@@ -855,7 +855,7 @@ void ASTMangler::appendType(Type type) {
855855
appendRetroactiveConformances(type);
856856
appendOperator("G");
857857
}
858-
addSubstitution(type.getPointer());
858+
addTypeSubstitution(type);
859859
return;
860860
}
861861
appendAnyGenericType(type->getAnyGeneric());
@@ -901,7 +901,7 @@ void ASTMangler::appendType(Type type) {
901901

902902
case TypeKind::DependentMember: {
903903
auto *DepTy = cast<DependentMemberType>(tybase);
904-
if (tryMangleSubstitution(DepTy))
904+
if (tryMangleTypeSubstitution(DepTy))
905905
return;
906906

907907
bool isAssocTypeAtDepth = false;
@@ -920,7 +920,7 @@ void ASTMangler::appendType(Type type) {
920920
appendAssociatedTypeName(DepTy);
921921
appendOperator("qa");
922922
}
923-
addSubstitution(DepTy);
923+
addTypeSubstitution(DepTy);
924924
return;
925925
}
926926

@@ -1633,7 +1633,7 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
16331633
}
16341634

16351635
// Try to mangle the entire name as a substitution.
1636-
if (tryMangleSubstitution(key.getPointer()))
1636+
if (tryMangleTypeSubstitution(key))
16371637
return;
16381638

16391639
// Try to mangle a symbolic reference for a nominal type.
@@ -1642,7 +1642,7 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
16421642
if (nominal && (!CanSymbolicReference || CanSymbolicReference(nominal))) {
16431643
appendSymbolicReference(nominal);
16441644
// Substitutions can refer back to the symbolic reference.
1645-
addSubstitution(key.getPointer());
1645+
addTypeSubstitution(key);
16461646
return;
16471647
}
16481648
}
@@ -1705,7 +1705,7 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
17051705
}
17061706
}
17071707

1708-
addSubstitution(key.getPointer());
1708+
addTypeSubstitution(key);
17091709
}
17101710

17111711
void ASTMangler::appendFunction(AnyFunctionType *fn, bool isFunctionMangling) {
@@ -1941,7 +1941,7 @@ void ASTMangler::appendRequirement(const Requirement &reqt) {
19411941

19421942
if (auto *DT = FirstTy->getAs<DependentMemberType>()) {
19431943
bool isAssocTypeAtDepth = false;
1944-
if (tryMangleSubstitution(DT)) {
1944+
if (tryMangleTypeSubstitution(DT)) {
19451945
switch (reqt.getKind()) {
19461946
case RequirementKind::Conformance:
19471947
return appendOperator("RQ");
@@ -1957,7 +1957,7 @@ void ASTMangler::appendRequirement(const Requirement &reqt) {
19571957
llvm_unreachable("bad requirement type");
19581958
}
19591959
GenericTypeParamType *gpBase = appendAssocType(DT, isAssocTypeAtDepth);
1960-
addSubstitution(DT);
1960+
addTypeSubstitution(DT);
19611961
assert(gpBase);
19621962
switch (reqt.getKind()) {
19631963
case RequirementKind::Conformance:
@@ -2043,24 +2043,54 @@ void ASTMangler::appendGenericSignatureParts(
20432043
appendOperator("r", StringRef(OpStorage.data(), OpStorage.size()));
20442044
}
20452045

2046+
// If the base type is known to have a single protocol conformance
2047+
// in the current generic context, then we don't need to disambiguate the
2048+
// associated type name by protocol.
2049+
DependentMemberType *
2050+
ASTMangler::dropProtocolFromAssociatedType(DependentMemberType *dmt) {
2051+
auto baseTy = dmt->getBase();
2052+
bool unambiguous = (!dmt->getAssocType() ||
2053+
CurGenericSignature->getConformsTo(baseTy).size() <= 1);
2054+
2055+
if (auto *baseDMT = baseTy->getAs<DependentMemberType>())
2056+
baseTy = dropProtocolFromAssociatedType(baseDMT);
2057+
2058+
if (unambiguous)
2059+
return DependentMemberType::get(baseTy, dmt->getName());
2060+
2061+
return DependentMemberType::get(baseTy, dmt->getAssocType());
2062+
}
2063+
2064+
Type
2065+
ASTMangler::dropProtocolsFromAssociatedTypes(Type type) {
2066+
if (!OptimizeProtocolNames || !CurGenericSignature)
2067+
return type;
2068+
2069+
if (!type->hasDependentMember())
2070+
return type;
2071+
2072+
return type.transform([&](Type t) -> Type {
2073+
if (auto *dmt = dyn_cast<DependentMemberType>(t.getPointer()))
2074+
return dropProtocolFromAssociatedType(dmt);
2075+
return t;
2076+
});
2077+
}
2078+
20462079
void ASTMangler::appendAssociatedTypeName(DependentMemberType *dmt) {
2047-
auto assocTy = dmt->getAssocType();
2048-
2049-
// If the base type is known to have a single protocol conformance
2050-
// in the current generic context, then we don't need to disambiguate the
2051-
// associated type name by protocol.
2052-
// This can result in getting the same mangled string for different
2053-
// DependentMemberTypes. This is not a problem but re-mangling might do more
2054-
// aggressive substitutions, which means that the re-mangled name may differ
2055-
// from the original mangled name.
2056-
// FIXME: We ought to be able to get to the generic signature from a
2057-
// dependent type, but can't yet. Shouldn't need this side channel.
2058-
2059-
appendIdentifier(assocTy->getName().str());
2060-
if (!OptimizeProtocolNames || !CurGenericSignature
2061-
|| CurGenericSignature->getConformsTo(dmt->getBase()).size() > 1) {
2062-
appendAnyGenericType(assocTy->getProtocol());
2080+
if (auto assocTy = dmt->getAssocType()) {
2081+
appendIdentifier(assocTy->getName().str());
2082+
2083+
// If the base type is known to have a single protocol conformance
2084+
// in the current generic context, then we don't need to disambiguate the
2085+
// associated type name by protocol.
2086+
if (!OptimizeProtocolNames || !CurGenericSignature
2087+
|| CurGenericSignature->getConformsTo(dmt->getBase()).size() > 1) {
2088+
appendAnyGenericType(assocTy->getProtocol());
2089+
}
2090+
return;
20632091
}
2092+
2093+
appendIdentifier(dmt->getName().str());
20642094
}
20652095

20662096
void ASTMangler::appendClosureEntity(

lib/Basic/Mangler.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,19 +180,9 @@ void Mangler::verify(StringRef nameStr) {
180180
if (Remangled == nameStr)
181181
return;
182182

183-
// There are cases (e.g. with dependent associated types) which results in
184-
// different remangled names. See ASTMangler::appendAssociatedTypeName.
185-
// This is no problem for the compiler, but we have to be more tolerant for
186-
// those cases. Instead we try to re-de-mangle the remangled name.
187-
NodePointer RootOfRemangled = Dem.demangleSymbol(Remangled);
188-
std::string ReDemangled = mangleNode(RootOfRemangled);
189-
if (Remangled == ReDemangled)
190-
return;
191-
192183
llvm::errs() << "Remangling failed:\n"
193184
"original = " << nameStr << "\n"
194-
"remangled = " << Remangled << "\n"
195-
"re-demangled = " << ReDemangled << '\n';
185+
"remangled = " << Remangled << "\n";
196186
abort();
197187
#endif
198188
}

lib/Demangling/Demangler.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,20 @@ NodePointer Demangler::demangleBoundGenericType() {
14581458
return NTy;
14591459
}
14601460

1461+
bool Demangle::nodeConsumesGenericArgs(Node *node) {
1462+
switch (node->getKind()) {
1463+
case Node::Kind::Variable:
1464+
case Node::Kind::Subscript:
1465+
case Node::Kind::ImplicitClosure:
1466+
case Node::Kind::ExplicitClosure:
1467+
case Node::Kind::DefaultArgumentInitializer:
1468+
case Node::Kind::Initializer:
1469+
return false;
1470+
default:
1471+
return true;
1472+
}
1473+
}
1474+
14611475
NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal,
14621476
const Vector<NodePointer> &TypeLists,
14631477
size_t TypeListIdx) {
@@ -1493,18 +1507,7 @@ NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal,
14931507
return nullptr;
14941508
NodePointer Context = Nominal->getFirstChild();
14951509

1496-
bool consumesGenericArgs = true;
1497-
switch (Nominal->getKind()) {
1498-
case Node::Kind::Variable:
1499-
case Node::Kind::ExplicitClosure:
1500-
case Node::Kind::Subscript:
1501-
// Those nodes can appear in the context but do not "consume" a generic
1502-
// argument type list.
1503-
consumesGenericArgs = false;
1504-
break;
1505-
default:
1506-
break;
1507-
}
1510+
bool consumesGenericArgs = nodeConsumesGenericArgs(Nominal);
15081511

15091512
NodePointer args = TypeLists[TypeListIdx];
15101513

0 commit comments

Comments
 (0)