Skip to content

Commit 4149c8f

Browse files
authored
[Runtime] Fix private generic type witness demangling failure (#25611)
This one’s screwily specific--if you have: * a private generic type, * with a nested generic type in it, * and the nested type conforms to a protocol with an associated type, * and that associated type’s witness is a generic type, * and some of the witness type’s generic parameters are generic parameters of the nested type, demangling would fail. The problem is that the substitution machinery in the runtime would consider there to be three, not two, generic context depths involved. Depth 1, which should correspond to the nested type, would instead have no generic parameters. The fix is to skip over depths with zero generic parameters. Fixes <rdar://problem/47773183>.
1 parent dcd1732 commit 4149c8f

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,12 +1677,13 @@ buildDescriptorPath(const ContextDescriptor *context) const {
16771677
hasNonKeyGenericParams = true;
16781678
}
16791679

1680-
// Form the path element.
1681-
descriptorPath.push_back(PathElement{localGenericParams,
1682-
context->getNumGenericParams(),
1683-
numKeyGenericParamsInParent,
1684-
numKeyGenericParamsHere,
1685-
hasNonKeyGenericParams});
1680+
// Form the path element if there are any generic parameters to be found.
1681+
if (numKeyGenericParamsHere != 0)
1682+
descriptorPath.push_back(PathElement{localGenericParams,
1683+
context->getNumGenericParams(),
1684+
numKeyGenericParamsInParent,
1685+
numKeyGenericParamsHere,
1686+
hasNonKeyGenericParams});
16861687
return numKeyGenericParamsInParent + numKeyGenericParamsHere;
16871688
}
16881689

test/Runtime/associated_type_demangle_private.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,44 @@ AssociatedTypeDemangleTests.test("generic anonymous contexts") {
7373
expectEqual("Inner<Int>", String(describing: getP2_A(C3<Int>.self)))
7474
}
7575

76+
// rdar://problem/47773183
77+
struct Pair<First, Second> {
78+
var first: First
79+
var second: Second
80+
}
81+
82+
protocol PairConvertible {
83+
associatedtype First
84+
associatedtype Second
85+
associatedtype PairType = Pair<First, Second>
86+
87+
var first: First { get }
88+
var second: Second { get }
89+
}
90+
91+
extension PairConvertible where PairType == Pair<First, Second> {
92+
var pair: PairType { Pair(first: first, second: second) }
93+
}
94+
95+
private struct Parent<Unused> {
96+
struct Nested<First, Second>: PairConvertible {
97+
var first: First
98+
var second: Second
99+
}
100+
}
101+
102+
AssociatedTypeDemangleTests.test("nested private generic types in associated type witnesses") {
103+
// Fixed in custom runtimes.
104+
if #available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, * ) {}
105+
// Fixed in Swift 5.1+ runtimes.
106+
else if #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) {}
107+
// Bug is still present in Swift 5.0 runtime.
108+
else {
109+
expectCrashLater(withMessage: "failed to demangle witness for associated type 'Second' in conformance")
110+
}
111+
112+
_ = Parent<Never>.Nested(first: "String", second: 0).pair
113+
}
114+
76115

77116
runAllTests()

0 commit comments

Comments
 (0)