Skip to content

Commit e95c3b3

Browse files
committed
Fix nested generic typerefs applying generic params at the wrong level
Generic params of typerefs are supposed to be "attached" on the level they belong, not as a flat list, unlike other parts of the system. Fix the application of bound generic params by checking how many were already applied in the hierarchy and ignoring them.
1 parent c4dd271 commit e95c3b3

File tree

2 files changed

+64
-27
lines changed

2 files changed

+64
-27
lines changed

include/swift/Reflection/TypeRef.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,14 +283,38 @@ class NominalTypeRef final : public TypeRef, public NominalTypeTrait {
283283
class BoundGenericTypeRef final : public TypeRef, public NominalTypeTrait {
284284
std::vector<const TypeRef *> GenericParams;
285285

286+
static uint64_t
287+
GetNumberOfGenericParametersInHierarchy(const TypeRef *typeref) {
288+
uint64_t count = 0;
289+
290+
// Only nominal and bound generic typeref have parents.
291+
if (auto nominalTyperef = llvm::dyn_cast_or_null<NominalTypeRef>(typeref)) {
292+
if (auto *parent = nominalTyperef->getParent())
293+
count = GetNumberOfGenericParametersInHierarchy(parent);
294+
} else if (auto genericTyperef =
295+
llvm::dyn_cast_or_null<BoundGenericTypeRef>(typeref)) {
296+
if (auto *parent = genericTyperef->getParent())
297+
count = GetNumberOfGenericParametersInHierarchy(parent);
298+
count += genericTyperef->getGenericParams().size();
299+
}
300+
301+
return count;
302+
}
303+
286304
static TypeRefID Profile(const std::string &MangledName,
287305
const std::vector<const TypeRef *> &GenericParams,
288306
const TypeRef *Parent) {
289307
TypeRefID ID;
290308
ID.addPointer(Parent);
291309
ID.addString(MangledName);
292-
for (auto Param : GenericParams)
293-
ID.addPointer(Param);
310+
uint64_t StartIndex = 0;
311+
if (Parent)
312+
StartIndex = GetNumberOfGenericParametersInHierarchy(Parent);
313+
314+
// GenericParams contains a flat vector of parameters used in the whole
315+
// typeref hierarchy, so we skip the ones that belong to our parents.
316+
for (auto i = StartIndex; i < GenericParams.size(); ++i)
317+
ID.addPointer(GenericParams[i]);
294318
return ID;
295319
}
296320

include/swift/Remote/MetadataReader.h

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2905,25 +2905,8 @@ class MetadataReader {
29052905
return builtSubsts;
29062906
}
29072907

2908-
BuiltType readNominalTypeFromMetadata(MetadataRef origMetadata,
2909-
bool skipArtificialSubclasses = false) {
2910-
auto metadata = origMetadata;
2911-
auto descriptorAddress =
2912-
readAddressOfNominalTypeDescriptor(metadata,
2913-
skipArtificialSubclasses);
2914-
if (!descriptorAddress)
2915-
return BuiltType();
2916-
2917-
// If we've skipped an artificial subclasses, check the cache at
2918-
// the superclass. (This also protects against recursion.)
2919-
if (skipArtificialSubclasses && metadata != origMetadata) {
2920-
auto it = TypeCache.find(getAddress(metadata));
2921-
if (it != TypeCache.end())
2922-
return it->second;
2923-
}
2924-
2925-
// Read the nominal type descriptor.
2926-
ContextDescriptorRef descriptor = readContextDescriptor(descriptorAddress);
2908+
BuiltType readNominalTypeFromDescriptor(MetadataRef metadata,
2909+
ContextDescriptorRef descriptor) {
29272910
if (!descriptor)
29282911
return BuiltType();
29292912

@@ -2932,34 +2915,64 @@ class MetadataReader {
29322915
if (!typeDecl)
29332916
return BuiltType();
29342917

2918+
// Attempt to build the parent (if it exists).
2919+
BuiltType parent;
2920+
if (auto parentDescriptor = readParentContextDescriptor(descriptor))
2921+
if (parentDescriptor->isResolved())
2922+
if (auto resolvedParent = parentDescriptor->getResolved())
2923+
parent = readNominalTypeFromDescriptor(metadata, resolvedParent);
2924+
29352925
// Build the nominal type.
29362926
BuiltType nominal;
29372927
if (descriptor->isGeneric()) {
29382928
// Resolve the generic arguments.
29392929
auto builtGenerics = getGenericSubst(metadata, descriptor);
29402930
if (builtGenerics.empty())
29412931
return BuiltType();
2942-
nominal = Builder.createBoundGenericType(typeDecl, builtGenerics);
2932+
nominal = Builder.createBoundGenericType(typeDecl, builtGenerics, parent);
29432933
} else {
2944-
nominal = Builder.createNominalType(typeDecl);
2934+
nominal = Builder.createNominalType(typeDecl, parent);
2935+
}
2936+
2937+
return nominal;
2938+
}
2939+
2940+
BuiltType readNominalTypeFromMetadata(MetadataRef origMetadata,
2941+
bool skipArtificialSubclasses = false) {
2942+
auto metadata = origMetadata;
2943+
auto descriptorAddress =
2944+
readAddressOfNominalTypeDescriptor(metadata, skipArtificialSubclasses);
2945+
if (!descriptorAddress)
2946+
return BuiltType();
2947+
2948+
// If we've skipped an artificial subclasses, check the cache at
2949+
// the superclass. (This also protects against recursion.)
2950+
if (skipArtificialSubclasses && metadata != origMetadata) {
2951+
auto it = TypeCache.find(getAddress(metadata));
2952+
if (it != TypeCache.end())
2953+
return it->second;
29452954
}
29462955

2956+
// Read the nominal type descriptor.
2957+
ContextDescriptorRef descriptor = readContextDescriptor(descriptorAddress);
2958+
auto nominal = readNominalTypeFromDescriptor(origMetadata, descriptor);
2959+
29472960
if (!nominal)
29482961
return BuiltType();
2949-
2962+
29502963
TypeCache[getAddress(metadata)] = nominal;
29512964

29522965
// If we've skipped an artificial subclass, remove the
29532966
// recursion-protection entry we made for it.
29542967
if (skipArtificialSubclasses && metadata != origMetadata) {
29552968
TypeCache.erase(getAddress(origMetadata));
29562969
}
2957-
29582970
return nominal;
29592971
}
29602972

2961-
BuiltType readNominalTypeFromClassMetadata(MetadataRef origMetadata,
2962-
bool skipArtificialSubclasses = false) {
2973+
BuiltType
2974+
readNominalTypeFromClassMetadata(MetadataRef origMetadata,
2975+
bool skipArtificialSubclasses = false) {
29632976
auto classMeta = cast<TargetClassMetadata>(origMetadata);
29642977
if (classMeta->isTypeMetadata())
29652978
return readNominalTypeFromMetadata(origMetadata, skipArtificialSubclasses);

0 commit comments

Comments
 (0)