Skip to content

Commit ad4cb5f

Browse files
committed
Mangler: Correctly record substitutions when dropping protocols from associated types
1 parent 535f5bd commit ad4cb5f

File tree

3 files changed

+71
-29
lines changed

3 files changed

+71
-29
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);

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(

test/SILGen/keypath_witness_overrides.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ where OS.Index: Hashable {
1313
// CHECK-SAME: id #OverridesSetter.subscript!getter.1
1414
// CHECK-SAME: getter @$s18protocol_overrides14OriginalGetterPy7ElementQz5IndexQzcipAA15OverridesSetterRzSHAGRQlxxTK
1515
// CHECK-SAME: setter @$s18protocol_overrides10AddsSetterPy7ElementQz5IndexQzcipAA09OverridesD0RzSHAGRQlxxTk
16-
// CHECK-SAME: indices_equals @$s5Index18protocol_overrides14OriginalGetterPQzAB15OverridesSetterRzSHAERQlTH
17-
// CHECK-SAME: indices_hash @$s5Index18protocol_overrides14OriginalGetterPQzAB15OverridesSetterRzSHAERQlTh
16+
// CHECK-SAME: indices_equals @$s5Index18protocol_overrides14OriginalGetterPQzAB15OverridesSetterRzSHAARpzlTH
17+
// CHECK-SAME: indices_hash @$s5Index18protocol_overrides14OriginalGetterPQzAB15OverridesSetterRzSHAARpzlTh
1818
let keypath = \OS.[index]
1919
return keypath
2020
}

0 commit comments

Comments
 (0)