Skip to content

Commit 6817c53

Browse files
committed
Mangle associated types of opaque types like dependent member types.
The archetype mangling does not have enough information to accurately recover the associated type at runtime. This fixes rdar://problem/54084733. Although this changes the mangling in both runtime and symbols, this should not affect ABI, because there is no way for associated types of opaque types to be surfaced in the types of public declarations today.
1 parent 3c2d709 commit 6817c53

File tree

5 files changed

+144
-73
lines changed

5 files changed

+144
-73
lines changed

docs/ABI/Mangling.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,11 @@ Types
551551
type ::= assoc-type-name 'Qz' // shortcut for 'Qyz'
552552
type ::= assoc-type-list 'QY' GENERIC-PARAM-INDEX // associated type at depth
553553
type ::= assoc-type-list 'QZ' // shortcut for 'QYz'
554+
555+
#if SWIFT_RUNTIME_VERSION >= 5.2
556+
type ::= type assoc-type-name 'Qx' // associated type relative to base `type`
557+
type ::= type assoc-type-list 'QX' // associated type relative to base `type`
558+
#endif
554559

555560
protocol-list ::= protocol '_' protocol*
556561
protocol-list ::= empty-list

lib/AST/ASTMangler.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,22 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
10031003

10041004
case TypeKind::NestedArchetype: {
10051005
auto nestedType = cast<NestedArchetypeType>(tybase);
1006+
1007+
// Mangle associated types of opaque archetypes like dependent member
1008+
// types, so that they can be accurately demangled at runtime.
1009+
if (auto opaque =
1010+
dyn_cast<OpaqueTypeArchetypeType>(nestedType->getRoot())) {
1011+
if (tryMangleTypeSubstitution(nestedType))
1012+
return;
1013+
1014+
appendType(opaque);
1015+
bool isAssocTypeAtDepth = false;
1016+
appendAssocType(nestedType->getInterfaceType(), isAssocTypeAtDepth);
1017+
appendOperator(isAssocTypeAtDepth ? "QX" : "Qx");
1018+
addTypeSubstitution(nestedType);
1019+
return;
1020+
}
1021+
10061022
appendType(nestedType->getParent());
10071023
appendIdentifier(nestedType->getName().str());
10081024
appendOperator("Qa");

lib/Demangling/Demangler.cpp

Lines changed: 91 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,79 +1919,96 @@ NodePointer Demangler::demanglePrivateContextDescriptor() {
19191919

19201920
NodePointer Demangler::demangleArchetype() {
19211921
switch (nextChar()) {
1922-
case 'a': {
1923-
NodePointer Ident = popNode(Node::Kind::Identifier);
1924-
NodePointer ArcheTy = popTypeAndGetChild();
1925-
NodePointer AssocTy = createType(
1926-
createWithChildren(Node::Kind::AssociatedTypeRef, ArcheTy, Ident));
1927-
addSubstitution(AssocTy);
1928-
return AssocTy;
1929-
}
1930-
case 'O': {
1931-
auto definingContext = popContext();
1932-
return createWithChild(Node::Kind::OpaqueReturnTypeOf, definingContext);
1933-
}
1934-
case 'o': {
1935-
auto index = demangleIndex();
1936-
Vector<NodePointer> boundGenericArgs;
1937-
NodePointer retroactiveConformances;
1938-
if (!demangleBoundGenerics(boundGenericArgs, retroactiveConformances))
1939-
return nullptr;
1940-
auto Name = popNode();
1941-
auto opaque = createWithChildren(Node::Kind::OpaqueType, Name,
1942-
createNode(Node::Kind::Index, index));
1943-
auto boundGenerics = createNode(Node::Kind::TypeList);
1944-
for (unsigned i = boundGenericArgs.size(); i-- > 0;)
1945-
boundGenerics->addChild(boundGenericArgs[i], *this);
1946-
opaque->addChild(boundGenerics, *this);
1947-
if (retroactiveConformances)
1948-
opaque->addChild(retroactiveConformances, *this);
1949-
1950-
auto opaqueTy = createType(opaque);
1951-
addSubstitution(opaqueTy);
1952-
return opaqueTy;
1953-
}
1954-
case 'r': {
1955-
return createType(createNode(Node::Kind::OpaqueReturnType));
1956-
}
1957-
case 'y': {
1958-
NodePointer T = demangleAssociatedTypeSimple(demangleGenericParamIndex());
1959-
addSubstitution(T);
1960-
return T;
1961-
}
1962-
case 'z': {
1963-
NodePointer T = demangleAssociatedTypeSimple(
1964-
getDependentGenericParamType(0, 0));
1965-
addSubstitution(T);
1966-
return T;
1967-
}
1968-
case 'Y': {
1969-
NodePointer T = demangleAssociatedTypeCompound(
1970-
demangleGenericParamIndex());
1971-
addSubstitution(T);
1972-
return T;
1973-
}
1974-
case 'Z': {
1975-
NodePointer T = demangleAssociatedTypeCompound(
1976-
getDependentGenericParamType(0, 0));
1977-
addSubstitution(T);
1978-
return T;
1979-
}
1980-
default:
1922+
case 'a': {
1923+
NodePointer Ident = popNode(Node::Kind::Identifier);
1924+
NodePointer ArcheTy = popTypeAndGetChild();
1925+
NodePointer AssocTy = createType(
1926+
createWithChildren(Node::Kind::AssociatedTypeRef, ArcheTy, Ident));
1927+
addSubstitution(AssocTy);
1928+
return AssocTy;
1929+
}
1930+
case 'O': {
1931+
auto definingContext = popContext();
1932+
return createWithChild(Node::Kind::OpaqueReturnTypeOf, definingContext);
1933+
}
1934+
case 'o': {
1935+
auto index = demangleIndex();
1936+
Vector<NodePointer> boundGenericArgs;
1937+
NodePointer retroactiveConformances;
1938+
if (!demangleBoundGenerics(boundGenericArgs, retroactiveConformances))
19811939
return nullptr;
1940+
auto Name = popNode();
1941+
auto opaque = createWithChildren(Node::Kind::OpaqueType, Name,
1942+
createNode(Node::Kind::Index, index));
1943+
auto boundGenerics = createNode(Node::Kind::TypeList);
1944+
for (unsigned i = boundGenericArgs.size(); i-- > 0;)
1945+
boundGenerics->addChild(boundGenericArgs[i], *this);
1946+
opaque->addChild(boundGenerics, *this);
1947+
if (retroactiveConformances)
1948+
opaque->addChild(retroactiveConformances, *this);
1949+
1950+
auto opaqueTy = createType(opaque);
1951+
addSubstitution(opaqueTy);
1952+
return opaqueTy;
1953+
}
1954+
case 'r': {
1955+
return createType(createNode(Node::Kind::OpaqueReturnType));
1956+
}
1957+
1958+
case 'x': {
1959+
NodePointer T = demangleAssociatedTypeSimple(nullptr);
1960+
addSubstitution(T);
1961+
return T;
1962+
}
1963+
1964+
case 'X': {
1965+
NodePointer T = demangleAssociatedTypeCompound(nullptr);
1966+
addSubstitution(T);
1967+
return T;
1968+
}
1969+
1970+
case 'y': {
1971+
NodePointer T = demangleAssociatedTypeSimple(demangleGenericParamIndex());
1972+
addSubstitution(T);
1973+
return T;
1974+
}
1975+
case 'Y': {
1976+
NodePointer T = demangleAssociatedTypeCompound(
1977+
demangleGenericParamIndex());
1978+
addSubstitution(T);
1979+
return T;
1980+
}
1981+
1982+
case 'z': {
1983+
NodePointer T = demangleAssociatedTypeSimple(
1984+
getDependentGenericParamType(0, 0));
1985+
addSubstitution(T);
1986+
return T;
1987+
}
1988+
case 'Z': {
1989+
NodePointer T = demangleAssociatedTypeCompound(
1990+
getDependentGenericParamType(0, 0));
1991+
addSubstitution(T);
1992+
return T;
1993+
}
1994+
default:
1995+
return nullptr;
19821996
}
19831997
}
19841998

1985-
NodePointer Demangler::demangleAssociatedTypeSimple(
1986-
NodePointer GenericParamIdx) {
1987-
NodePointer GPI = createType(GenericParamIdx);
1999+
NodePointer Demangler::demangleAssociatedTypeSimple(NodePointer Base) {
19882000
NodePointer ATName = popAssocTypeName();
2001+
NodePointer BaseTy;
2002+
if (Base) {
2003+
BaseTy = createType(Base);
2004+
} else {
2005+
BaseTy = popNode(Node::Kind::Type);
2006+
}
19892007
return createType(createWithChildren(Node::Kind::DependentMemberType,
1990-
GPI, ATName));
2008+
BaseTy, ATName));
19912009
}
19922010

1993-
NodePointer Demangler::demangleAssociatedTypeCompound(
1994-
NodePointer GenericParamIdx) {
2011+
NodePointer Demangler::demangleAssociatedTypeCompound(NodePointer Base) {
19952012
Vector<NodePointer> AssocTyNames(*this, 4);
19962013
bool firstElem = false;
19972014
do {
@@ -2001,15 +2018,19 @@ NodePointer Demangler::demangleAssociatedTypeCompound(
20012018
return nullptr;
20022019
AssocTyNames.push_back(AssocTyName, *this);
20032020
} while (!firstElem);
2004-
2005-
NodePointer Base = GenericParamIdx;
2021+
2022+
NodePointer BaseTy;
2023+
if (Base)
2024+
BaseTy = createType(Base);
2025+
else
2026+
BaseTy = popNode(Node::Kind::Type);
20062027

20072028
while (NodePointer AssocTy = AssocTyNames.pop_back_val()) {
20082029
NodePointer depTy = createNode(Node::Kind::DependentMemberType);
2009-
depTy = addChild(depTy, createType(Base));
2010-
Base = addChild(depTy, AssocTy);
2030+
depTy = addChild(depTy, BaseTy);
2031+
BaseTy = createType(addChild(depTy, AssocTy));
20112032
}
2012-
return createType(Base);
2033+
return BaseTy;
20132034
}
20142035

20152036
NodePointer Demangler::popAssocTypeName() {

lib/Demangling/Remangler.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,11 @@ std::pair<int, Node *> Remangler::mangleConstrainedType(Node *node) {
424424
Chain.push_back(node->getChild(1), Factory);
425425
node = getChildOfType(node->getFirstChild());
426426
}
427-
assert(node->getKind() == Node::Kind::DependentGenericParamType);
427+
428+
if (node->getKind() != Node::Kind::DependentGenericParamType) {
429+
mangle(node);
430+
node = nullptr;
431+
}
428432

429433
const char *ListSeparator = (Chain.size() > 1 ? "_" : "");
430434
for (unsigned i = 1, n = Chain.size(); i <= n; ++i) {
@@ -811,6 +815,7 @@ void Remangler::mangleDependentGenericConformanceRequirement(Node *node) {
811815
if (ProtoOrClass->getFirstChild()->getKind() == Node::Kind::Protocol) {
812816
manglePureProtocol(ProtoOrClass);
813817
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
818+
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
814819
switch (NumMembersAndParamIdx.first) {
815820
case -1: Buffer << "RQ"; return; // substitution
816821
case 0: Buffer << "R"; break;
@@ -822,6 +827,7 @@ void Remangler::mangleDependentGenericConformanceRequirement(Node *node) {
822827
}
823828
mangle(ProtoOrClass);
824829
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
830+
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
825831
switch (NumMembersAndParamIdx.first) {
826832
case -1: Buffer << "RB"; return; // substitution
827833
case 0: Buffer << "Rb"; break;
@@ -849,6 +855,7 @@ void Remangler::mangleDependentGenericParamType(Node *node) {
849855
void Remangler::mangleDependentGenericSameTypeRequirement(Node *node) {
850856
mangleChildNode(node, 1);
851857
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
858+
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
852859
switch (NumMembersAndParamIdx.first) {
853860
case -1: Buffer << "RS"; return; // substitution
854861
case 0: Buffer << "Rs"; break;
@@ -860,6 +867,7 @@ void Remangler::mangleDependentGenericSameTypeRequirement(Node *node) {
860867

861868
void Remangler::mangleDependentGenericLayoutRequirement(Node *node) {
862869
auto NumMembersAndParamIdx = mangleConstrainedType(node->getChild(0));
870+
assert(NumMembersAndParamIdx.first < 0 || NumMembersAndParamIdx.second);
863871
switch (NumMembersAndParamIdx.first) {
864872
case -1: Buffer << "RL"; break; // substitution
865873
case 0: Buffer << "Rl"; break;
@@ -922,11 +930,19 @@ void Remangler::mangleDependentMemberType(Node *node) {
922930
unreachable("wrong dependent member type");
923931
case 1:
924932
Buffer << 'Q';
925-
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second, "y", 'z');
933+
if (auto dependentBase = NumMembersAndParamIdx.second) {
934+
mangleDependentGenericParamIndex(dependentBase, "y", 'z');
935+
} else {
936+
Buffer << 'x';
937+
}
926938
break;
927939
default:
928940
Buffer << 'Q';
929-
mangleDependentGenericParamIndex(NumMembersAndParamIdx.second, "Y", 'Z');
941+
if (auto dependentBase = NumMembersAndParamIdx.second) {
942+
mangleDependentGenericParamIndex(dependentBase, "Y", 'Z');
943+
} else {
944+
Buffer << 'X';
945+
}
930946
break;
931947
}
932948
}

test/Interpreter/opaque_return_type_protocol_ext.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,16 @@ if #available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) {
7979
print("i'm getting way too old for this sh")
8080
print("way too old")
8181
}
82+
83+
@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *)
84+
dynamic func opaqueAssocTypeUnderlyingType() -> some Any {
85+
return g().f()
86+
}
87+
88+
if #available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *) {
89+
let x = opaqueAssocTypeUnderlyingType()
90+
// CHECK: {{[1, 2, 3]|too old}}
91+
print(x)
92+
} else {
93+
print("nope, still too old")
94+
}

0 commit comments

Comments
 (0)