Fix issues with runtime reporting incorrect types for nested generics

Fixes: https://github.com/apple/swift/issues/60565
This commit is contained in:
Nuri Amari
2022-10-27 14:12:06 -07:00
parent dc3978f6fb
commit 66f993194a
3 changed files with 50 additions and 26 deletions

View File

@@ -558,9 +558,7 @@ public:
auto kind = node->getKind();
// Kinds who have a "BoundGeneric..." variant.
if (kind != Node::Kind::Class && kind != Node::Kind::Structure &&
kind != Node::Kind::Enum && kind != Node::Kind::Protocol &&
kind != Node::Kind::OtherNominalType && kind != Node::Kind::TypeAlias &&
kind != Node::Kind::Function)
kind != Node::Kind::Enum)
return nullptr;
auto mangling = Demangle::mangleNode(node);
if (!mangling.isSuccess())
@@ -572,9 +570,23 @@ public:
args.end() - argsIndex - numGenericArgs, args.end() - argsIndex);
const BoundGenericTypeRef *parent = nullptr;
if (node->hasChildren())
if (node->hasChildren()) {
// Skip over nodes that are not of type class, enum or struct
auto parentNode = node->getFirstChild();
while (parentNode->getKind() != Node::Kind::Class &&
parentNode->getKind() != Node::Kind::Structure &&
parentNode->getKind() != Node::Kind::Enum) {
if (parentNode->hasChildren()) {
parentNode = parentNode->getFirstChild();
} else {
parentNode = nullptr;
break;
}
}
if (parentNode)
parent = createBoundGenericTypeReconstructingParent(
node->getFirstChild(), decl, --shapeIndex, args, argsIndex + numGenericArgs);
parentNode, decl, --shapeIndex, args, argsIndex + numGenericArgs);
}
return BoundGenericTypeRef::create(*this, mangling.result(), genericParams,
parent);

View File

@@ -2906,9 +2906,11 @@ private:
template <
typename T = BuilderType,
typename std::enable_if_t<
!std::is_same<
bool,
decltype(T::needsToPrecomputeParentGenericContextShapes)>::value,
!(std::is_same<
const bool,
decltype(T::needsToPrecomputeParentGenericContextShapes)>::
value &&
T::needsToPrecomputeParentGenericContextShapes),
bool> = true>
BuiltTypeDecl buildNominalTypeDecl(ContextDescriptorRef descriptor) {
// Build the demangling tree from the context tree.
@@ -2921,12 +2923,13 @@ private:
return decl;
}
template <
typename T = BuilderType,
template <typename T = BuilderType,
typename std::enable_if_t<
std::is_same<
bool,
decltype(T::needsToPrecomputeParentGenericContextShapes)>::value,
const bool,
decltype(T::needsToPrecomputeParentGenericContextShapes)>::
value &&
T::needsToPrecomputeParentGenericContextShapes,
bool> = true>
BuiltTypeDecl buildNominalTypeDecl(ContextDescriptorRef descriptor) {
// Build the demangling tree from the context tree.
@@ -2944,12 +2947,17 @@ private:
countLevels(parentContext, runningCount);
auto genericContext = current->getGenericContext();
if (!genericContext)
return;
// Only consider generic contexts of type class, enum or struct.
// There are other context types that can be generic, but they should
// not affect the generic shape.
if (genericContext &&
(current->getKind() == ContextDescriptorKind::Class ||
current->getKind() == ContextDescriptorKind::Enum ||
current->getKind() == ContextDescriptorKind::Struct)) {
auto contextHeader = genericContext->getGenericContextHeader();
paramsPerLevel.emplace_back(contextHeader.NumParams - runningCount);
runningCount += paramsPerLevel.back();
}
};
countLevels(descriptor, runningCount);
BuiltTypeDecl decl = Builder.createTypeDecl(node, paramsPerLevel);

View File

@@ -30,15 +30,19 @@ reflect(object: obj)
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (bound_generic_class reflect_nested.OuterGeneric.Inner.Innermost
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.String)
// CHECK-64-NEXT: (bound_generic_class reflect_nested.OuterGeneric.Inner
// CHECK-64-NEXT: (bound_generic_class reflect_nested.OuterGeneric
// CHECK-64-NEXT: (struct Swift.Int))))
// CHECK-32: Reflecting an object.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (bound_generic_class reflect_nested.OuterGeneric.Inner.Innermost
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.String)
// CHECK-32-NEXT: (bound_generic_class reflect_nested.OuterGeneric.Inner
// CHECK-32-NEXT: (bound_generic_class reflect_nested.OuterGeneric
// CHECK-32-NEXT: (struct Swift.Int))))
doneReflecting()