Skip to content

Commit 868feb7

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 399d5f3 commit 868feb7

File tree

2 files changed

+71
-27
lines changed

2 files changed

+71
-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: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@
3030
#include "swift/Runtime/HeapObject.h"
3131
#include "swift/Basic/Unreachable.h"
3232

33+
#include <type_traits>
3334
#include <vector>
3435
#include <unordered_map>
3536

3637
#include <inttypes.h>
3738

3839
namespace swift {
40+
namespace reflection {
41+
class TypeRefBuilder;
42+
}
3943
namespace remote {
4044

4145
template <typename BuiltType>
@@ -2905,25 +2909,8 @@ class MetadataReader {
29052909
return builtSubsts;
29062910
}
29072911

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);
2912+
BuiltType readNominalTypeFromDescriptor(MetadataRef metadata,
2913+
ContextDescriptorRef descriptor) {
29272914
if (!descriptor)
29282915
return BuiltType();
29292916

@@ -2932,34 +2919,67 @@ class MetadataReader {
29322919
if (!typeDecl)
29332920
return BuiltType();
29342921

2922+
BuiltType parent;
2923+
// Attempt to build the parent (if it exists). We only do this when building
2924+
// typerefs as that's the only implementation of builder that actually needs
2925+
// the parent to build the nominal type correctly.
2926+
if (std::is_same<BuilderType, reflection::TypeRefBuilder>::value)
2927+
if (auto parentDescriptor = readParentContextDescriptor(descriptor))
2928+
if (parentDescriptor->isResolved())
2929+
if (auto resolvedParent = parentDescriptor->getResolved())
2930+
parent = readNominalTypeFromDescriptor(metadata, resolvedParent);
2931+
29352932
// Build the nominal type.
29362933
BuiltType nominal;
29372934
if (descriptor->isGeneric()) {
29382935
// Resolve the generic arguments.
29392936
auto builtGenerics = getGenericSubst(metadata, descriptor);
29402937
if (builtGenerics.empty())
29412938
return BuiltType();
2942-
nominal = Builder.createBoundGenericType(typeDecl, builtGenerics);
2939+
nominal = Builder.createBoundGenericType(typeDecl, builtGenerics, parent);
29432940
} else {
2944-
nominal = Builder.createNominalType(typeDecl);
2941+
nominal = Builder.createNominalType(typeDecl, parent);
29452942
}
29462943

2944+
return nominal;
2945+
}
2946+
2947+
BuiltType readNominalTypeFromMetadata(MetadataRef origMetadata,
2948+
bool skipArtificialSubclasses = false) {
2949+
auto metadata = origMetadata;
2950+
auto descriptorAddress =
2951+
readAddressOfNominalTypeDescriptor(metadata, skipArtificialSubclasses);
2952+
if (!descriptorAddress)
2953+
return BuiltType();
2954+
2955+
// If we've skipped an artificial subclasses, check the cache at
2956+
// the superclass. (This also protects against recursion.)
2957+
if (skipArtificialSubclasses && metadata != origMetadata) {
2958+
auto it = TypeCache.find(getAddress(metadata));
2959+
if (it != TypeCache.end())
2960+
return it->second;
2961+
}
2962+
2963+
// Read the nominal type descriptor.
2964+
ContextDescriptorRef descriptor = readContextDescriptor(descriptorAddress);
2965+
auto nominal = readNominalTypeFromDescriptor(origMetadata, descriptor);
2966+
29472967
if (!nominal)
29482968
return BuiltType();
2949-
2969+
29502970
TypeCache[getAddress(metadata)] = nominal;
29512971

29522972
// If we've skipped an artificial subclass, remove the
29532973
// recursion-protection entry we made for it.
29542974
if (skipArtificialSubclasses && metadata != origMetadata) {
29552975
TypeCache.erase(getAddress(origMetadata));
29562976
}
2957-
29582977
return nominal;
29592978
}
29602979

2961-
BuiltType readNominalTypeFromClassMetadata(MetadataRef origMetadata,
2962-
bool skipArtificialSubclasses = false) {
2980+
BuiltType
2981+
readNominalTypeFromClassMetadata(MetadataRef origMetadata,
2982+
bool skipArtificialSubclasses = false) {
29632983
auto classMeta = cast<TargetClassMetadata>(origMetadata);
29642984
if (classMeta->isTypeMetadata())
29652985
return readNominalTypeFromMetadata(origMetadata, skipArtificialSubclasses);

0 commit comments

Comments
 (0)