Skip to content

Commit 659c497

Browse files
authored
Merge pull request #25984 from jrose-apple/same-gamgee
[runtime] Handle same-type constraints when resolving generic params rdar://problem/52364601
2 parents dd7d14c + 4b8068d commit 659c497

File tree

6 files changed

+235
-38
lines changed

6 files changed

+235
-38
lines changed

include/swift/ABI/Metadata.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,12 @@ struct TargetContextDescriptor {
24852485
? genericContext->getGenericContextHeader().NumParams
24862486
: 0;
24872487
}
2488+
2489+
#ifndef NDEBUG
2490+
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
2491+
"only for use in the debugger");
2492+
#endif
2493+
24882494
private:
24892495
TargetContextDescriptor(const TargetContextDescriptor &) = delete;
24902496
TargetContextDescriptor(TargetContextDescriptor &&) = delete;
@@ -3649,11 +3655,6 @@ class TargetTypeContextDescriptor
36493655
return cd->getKind() >= ContextDescriptorKind::Type_First
36503656
&& cd->getKind() <= ContextDescriptorKind::Type_Last;
36513657
}
3652-
3653-
#ifndef NDEBUG
3654-
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
3655-
"Only meant for use in the debugger");
3656-
#endif
36573658
};
36583659

36593660
using TypeContextDescriptor = TargetTypeContextDescriptor<InProcess>;

stdlib/public/runtime/Metadata.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3945,20 +3945,33 @@ void Metadata::dump() const {
39453945
printf("TargetMetadata.\n");
39463946
printf("Kind: %s.\n", getStringForMetadataKind(getKind()).data());
39473947
printf("Value Witnesses: %p.\n", getValueWitnesses());
3948-
printf("Class Object: %p.\n", getClassObject());
3949-
printf("Type Context Description: %p.\n", getTypeContextDescriptor());
3948+
3949+
auto *contextDescriptor = getTypeContextDescriptor();
3950+
printf("Name: %s.\n", contextDescriptor->Name.get());
3951+
printf("Type Context Description: %p.\n", contextDescriptor);
39503952
printf("Generic Args: %p.\n", getGenericArgs());
3953+
3954+
#if SWIFT_OBJC_INTEROP
3955+
if (auto *classObject = getClassObject()) {
3956+
printf("ObjC Name: %s.\n", class_getName(
3957+
reinterpret_cast<Class>(const_cast<ClassMetadata *>(classObject))));
3958+
printf("Class Object: %p.\n", classObject);
3959+
}
3960+
#endif
39513961
}
39523962

39533963
template <>
39543964
LLVM_ATTRIBUTE_USED
3955-
void TypeContextDescriptor::dump() const {
3965+
void ContextDescriptor::dump() const {
39563966
printf("TargetTypeContextDescriptor.\n");
39573967
printf("Flags: 0x%x.\n", this->Flags.getIntValue());
39583968
printf("Parent: %p.\n", this->Parent.get());
3959-
printf("Name: %s.\n", Name.get());
3960-
printf("Access function: %p.\n", static_cast<void *>(getAccessFunction()));
3961-
printf("Fields: %p.\n", Fields.get());
3969+
if (auto *typeDescriptor = dyn_cast<TypeContextDescriptor>(this)) {
3970+
printf("Name: %s.\n", typeDescriptor->Name.get());
3971+
printf("Fields: %p.\n", typeDescriptor->Fields.get());
3972+
printf("Access function: %p.\n",
3973+
static_cast<void *>(typeDescriptor->getAccessFunction()));
3974+
}
39623975
}
39633976

39643977
template<>

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,17 @@ _findContextDescriptor(Demangle::NodePointer node,
246246
Demangle::Demangler &Dem);
247247

248248
/// Find the context descriptor for the type extended by the given extension.
249+
///
250+
/// If \p maybeExtension isn't actually an extension context, returns nullptr.
249251
static const ContextDescriptor *
250-
_findExtendedTypeContextDescriptor(const ExtensionContextDescriptor *extension,
252+
_findExtendedTypeContextDescriptor(const ContextDescriptor *maybeExtension,
251253
Demangler &demangler,
252254
Demangle::NodePointer *demangledNode
253255
= nullptr) {
256+
auto extension = dyn_cast<ExtensionContextDescriptor>(maybeExtension);
257+
if (!extension)
258+
return nullptr;
259+
254260
Demangle::NodePointer localNode;
255261
Demangle::NodePointer &node = demangledNode ? *demangledNode : localNode;
256262

@@ -844,28 +850,26 @@ bool swift::_gatherGenericParameterCounts(
844850
DemanglerForRuntimeTypeResolution<> demangler;
845851
demangler.providePreallocatedMemory(BorrowFrom);
846852

847-
if (auto extension = dyn_cast<ExtensionContextDescriptor>(descriptor)) {
848-
// If we have an nominal type extension descriptor, extract the extended type
853+
if (auto extension = _findExtendedTypeContextDescriptor(descriptor,
854+
demangler)) {
855+
// If we have a nominal type extension descriptor, extract the extended type
849856
// and use that. If the extension is not nominal, then we can use the
850857
// extension's own signature.
851-
if (auto extendedType =
852-
_findExtendedTypeContextDescriptor(extension, demangler)) {
853-
descriptor = extendedType;
854-
}
858+
descriptor = extension;
855859
}
856860

857861
// Once we hit a non-generic descriptor, we're done.
858862
if (!descriptor->isGeneric()) return false;
859863

860864
// Recurse to record the parent context's generic parameters.
861-
if (auto parent = descriptor->Parent.get())
862-
(void)_gatherGenericParameterCounts(parent, genericParamCounts, demangler);
865+
auto parent = descriptor->Parent.get();
866+
(void)_gatherGenericParameterCounts(parent, genericParamCounts, demangler);
863867

864868
// Record a new level of generic parameters if the count exceeds the
865869
// previous count.
866-
auto myCount =
867-
descriptor->getGenericContext()->getGenericContextHeader().NumParams;
868-
if (genericParamCounts.empty() || myCount > genericParamCounts.back()) {
870+
unsigned parentCount = parent->getNumGenericParams();
871+
unsigned myCount = descriptor->getNumGenericParams();
872+
if (myCount > parentCount) {
869873
genericParamCounts.push_back(myCount);
870874
return true;
871875
}
@@ -1658,32 +1662,50 @@ static void installGetClassHook() {
16581662
#endif
16591663

16601664
unsigned SubstGenericParametersFromMetadata::
1661-
buildDescriptorPath(const ContextDescriptor *context) const {
1665+
buildDescriptorPath(const ContextDescriptor *context,
1666+
Demangler &borrowFrom) const {
1667+
assert(sourceIsMetadata);
1668+
16621669
// Terminating condition: we don't have a context.
16631670
if (!context)
16641671
return 0;
16651672

1673+
DemanglerForRuntimeTypeResolution<> demangler;
1674+
demangler.providePreallocatedMemory(borrowFrom);
1675+
1676+
if (auto extension = _findExtendedTypeContextDescriptor(context, demangler)) {
1677+
// If we have a nominal type extension descriptor, extract the extended type
1678+
// and use that. If the extension is not nominal, then we can use the
1679+
// extension's own signature.
1680+
context = extension;
1681+
}
1682+
16661683
// Add the parent's contribution to the descriptor path.
1667-
unsigned numKeyGenericParamsInParent =
1668-
buildDescriptorPath(context->Parent.get());
1684+
const ContextDescriptor *parent = context->Parent.get();
1685+
unsigned numKeyGenericParamsInParent = buildDescriptorPath(parent, demangler);
16691686

16701687
// If this context is non-generic, we're done.
16711688
if (!context->isGeneric())
16721689
return numKeyGenericParamsInParent;
16731690

16741691
// Count the number of key generic params at this level.
1692+
auto allGenericParams = baseContext->getGenericContext()->getGenericParams();
1693+
unsigned parentCount = parent->getNumGenericParams();
1694+
unsigned localCount = context->getNumGenericParams();
1695+
auto localGenericParams = allGenericParams.slice(parentCount,
1696+
localCount - parentCount);
1697+
16751698
unsigned numKeyGenericParamsHere = 0;
16761699
bool hasNonKeyGenericParams = false;
1677-
auto localGenericParams = getLocalGenericParams(context);
16781700
for (const auto &genericParam : localGenericParams) {
16791701
if (genericParam.hasKeyArgument())
16801702
++numKeyGenericParamsHere;
16811703
else
16821704
hasNonKeyGenericParams = true;
16831705
}
16841706

1685-
// Form the path element if there are any generic parameters to be found.
1686-
if (numKeyGenericParamsHere != 0)
1707+
// Form the path element if there are any new generic parameters.
1708+
if (localCount > parentCount)
16871709
descriptorPath.push_back(PathElement{localGenericParams,
16881710
context->getNumGenericParams(),
16891711
numKeyGenericParamsInParent,
@@ -1738,7 +1760,8 @@ void SubstGenericParametersFromMetadata::setup() const {
17381760
return;
17391761

17401762
if (sourceIsMetadata && baseContext) {
1741-
numKeyGenericParameters = buildDescriptorPath(baseContext);
1763+
DemanglerForRuntimeTypeResolution<StackAllocatedDemangler<2048>> demangler;
1764+
numKeyGenericParameters = buildDescriptorPath(baseContext, demangler);
17421765
return;
17431766
}
17441767

stdlib/public/runtime/Private.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,8 @@ class TypeInfo {
309309
///
310310
/// \returns a pair containing the number of key generic parameters in
311311
/// the path up to this point.
312-
unsigned buildDescriptorPath(const ContextDescriptor *context) const;
312+
unsigned buildDescriptorPath(const ContextDescriptor *context,
313+
Demangler &demangler) const;
313314

314315
/// Builds a path from the generic environment.
315316
unsigned buildEnvironmentPath(

test/IRGen/nested_generics.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ protocol HasAssoc {
105105
associatedtype Assoc
106106
}
107107

108+
class SeparateGenericSuperclass<T> {}
109+
108110
enum Container<T : TagProtocol> {
109111
class _Superclass {}
110112
// CHECK-CONSTANTS-LABEL: @"$s15nested_generics9ContainerO9_SubclassCMn" =
@@ -127,27 +129,30 @@ enum Container<T : TagProtocol> {
127129
// CHECK-CONSTANTS-SAME: @"symbolic _____yx_G 15nested_generics9ContainerO11_SuperclassC"
128130
class _Subclass2<U: Collection>: _Superclass where T == U.Element {}
129131

130-
131132
// CHECK-CONSTANTS-LABEL: @"$s15nested_generics9ContainerO10_Subclass3CMn" =
132-
// FIXME: That "qd__" still causes problems: it's (depth: 1, index: 0), but
133-
// the runtime doesn't count the parameters at depth 0 correctly.
134133
// CHECK-CONSTANTS-SAME: @"symbolic _____y______qd__G 15nested_generics9ContainerO18_GenericSuperclassC AA5OuterO"
135134
class _GenericSuperclass<U> {}
136135
class _Subclass3<U>: _GenericSuperclass<U> where T == Outer {}
137136

137+
class MoreNesting {
138+
// CHECK-CONSTANTS-LABEL: @"$s15nested_generics9ContainerO11MoreNestingC9_SubclassCMn" =
139+
// CHECK-CONSTANTS-SAME: @"symbolic _____y______G 15nested_generics9ContainerO11_SuperclassC AA5OuterO"
140+
class _Subclass<U>: _Superclass where T == Outer {}
141+
}
142+
143+
// CHECK-CONSTANTS-LABEL: @"$s15nested_generics9ContainerO24_SeparateGenericSubclassCMn" =
144+
// CHECK-CONSTANTS-SAME: @"symbolic _____yxSgG 15nested_generics25SeparateGenericSuperclassC"
145+
class _SeparateGenericSubclass: SeparateGenericSuperclass<T?> {}
146+
138147
// CHECK-CONSTANTS-LABEL: @"$s15nested_generics9ContainerO6FieldsVMF" =
139148
// CHECK-CONSTANTS-SAME: @"symbolic _____ 15nested_generics5OuterO"
140-
// FIXME: This still causes problems: it's (depth: 1, index: 0), but
141-
// the runtime doesn't count the parameters at depth 0 correctly.
142149
// CHECK-CONSTANTS-SAME: @"symbolic qd__"
143150
struct Fields<U> where T == Outer {
144151
var x: T
145152
var y: U
146153
}
147154

148155
// CHECK-CONSTANTS-LABEL: @"$s15nested_generics9ContainerO5CasesOMF" =
149-
// FIXME: This still causes problems: it's (depth: 1, index: 0), but
150-
// the runtime doesn't count the parameters at depth 0 correctly.
151156
// CHECK-CONSTANTS-SAME: @"symbolic qd__"
152157
enum Cases<U> where T == Outer {
153158
case a(T)

0 commit comments

Comments
 (0)