Skip to content

Commit db14ae8

Browse files
authored
Merge pull request #65332 from tbkka/tbkka-RemoteMirror-nested-generics
[RemoteMirror] Fix lookup of generic type parameters
2 parents 6e1a6fb + 488fb82 commit db14ae8

File tree

4 files changed

+280
-110
lines changed

4 files changed

+280
-110
lines changed

include/swift/Remote/MetadataReader.h

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,19 +2959,13 @@ class MetadataReader {
29592959
// Only consider generic contexts of type class, enum or struct.
29602960
// There are other context types that can be generic, but they should
29612961
// not affect the generic shape.
2962-
if (current->getKind() == ContextDescriptorKind::Class ||
2963-
current->getKind() == ContextDescriptorKind::Enum ||
2964-
current->getKind() == ContextDescriptorKind::Struct) {
2965-
if (genericContext) {
2966-
auto contextHeader = genericContext->getGenericContextHeader();
2967-
paramsPerLevel.emplace_back(contextHeader.NumParams -
2968-
runningCount);
2969-
runningCount += paramsPerLevel.back();
2970-
} else {
2971-
// If there is no generic context, this is a non-generic type
2972-
// which has 0 generic parameters.
2973-
paramsPerLevel.emplace_back(0);
2974-
}
2962+
if (genericContext &&
2963+
(current->getKind() == ContextDescriptorKind::Class ||
2964+
current->getKind() == ContextDescriptorKind::Enum ||
2965+
current->getKind() == ContextDescriptorKind::Struct)) {
2966+
auto contextHeader = genericContext->getGenericContextHeader();
2967+
paramsPerLevel.emplace_back(contextHeader.NumParams - runningCount);
2968+
runningCount += paramsPerLevel.back();
29752969
}
29762970
};
29772971
countLevels(descriptor, runningCount);

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 103 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -567,65 +567,66 @@ class TypeRefBuilder {
567567
return nullptr;
568568
}
569569

570-
const BoundGenericTypeRef *createBoundGenericTypeReconstructingParent(
571-
const NodePointer node, const TypeRefDecl &decl, size_t shapeIndex,
572-
const llvm::ArrayRef<const TypeRef *> &args, size_t argsIndex) {
573-
if (!node || !node->hasChildren())
574-
return nullptr;
575-
576-
auto maybeGenericParamsPerLevel = decl.genericParamsPerLevel;
577-
if (!maybeGenericParamsPerLevel)
578-
return nullptr;
579-
580-
auto genericParamsPerLevel = *maybeGenericParamsPerLevel;
581-
582-
auto kind = node->getKind();
583-
// Kinds who have a "BoundGeneric..." variant.
584-
if (kind != Node::Kind::Class && kind != Node::Kind::Structure &&
585-
kind != Node::Kind::Enum)
586-
return nullptr;
587-
auto mangling = Demangle::mangleNode(node);
588-
if (!mangling.isSuccess())
589-
return nullptr;
590-
591-
if (shapeIndex >= genericParamsPerLevel.size())
592-
return nullptr;
593-
594-
auto numGenericArgs = genericParamsPerLevel[shapeIndex];
595-
596-
auto startOffsetFromEnd = argsIndex + numGenericArgs;
597-
auto endOffsetFromEnd = argsIndex;
598-
if (startOffsetFromEnd > args.size() || endOffsetFromEnd > args.size())
599-
return nullptr;
600-
601-
std::vector<const TypeRef *> genericParams(
602-
args.end() - startOffsetFromEnd, args.end() - endOffsetFromEnd);
603-
604-
const BoundGenericTypeRef *parent = nullptr;
605-
if (node->hasChildren()) {
606-
// Skip over nodes that are not of type class, enum or struct
607-
auto parentNode = node->getFirstChild();
608-
while (parentNode->getKind() != Node::Kind::Class &&
609-
parentNode->getKind() != Node::Kind::Structure &&
610-
parentNode->getKind() != Node::Kind::Enum) {
611-
if (parentNode->hasChildren()) {
612-
parentNode = parentNode->getFirstChild();
613-
} else {
614-
parentNode = nullptr;
615-
break;
616-
}
570+
// Construct a bound generic type ref along with the parent type info
571+
// The parent list contains every parent type with at least 1 generic
572+
// type parameter.
573+
const BoundGenericTypeRef *reconstructParentsOfBoundGenericType(
574+
const NodePointer startNode,
575+
const std::vector<size_t> &genericParamsPerLevel,
576+
const llvm::ArrayRef<const TypeRef *> &args)
577+
{
578+
// Collect the first N parents that potentially have generic args
579+
// (Ignore the last genericParamPerLevel, which
580+
// applies to the startNode itself.)
581+
std::vector<NodePointer> nodes;
582+
NodePointer node = startNode;
583+
while (nodes.size() < genericParamsPerLevel.size() - 1) {
584+
if (!node || !node->hasChildren()) {
585+
return nullptr;
617586
}
618-
if (parentNode) {
619-
if (shapeIndex > 0)
620-
parent = createBoundGenericTypeReconstructingParent(
621-
parentNode, decl, --shapeIndex, args, argsIndex + numGenericArgs);
622-
else
623-
return nullptr;
587+
node = node->getFirstChild();
588+
switch (node->getKind()) {
589+
case Node::Kind::Class:
590+
case Node::Kind::Structure:
591+
case Node::Kind::Enum:
592+
nodes.push_back(node);
593+
break;
594+
default:
595+
break;
624596
}
625597
}
598+
assert(nodes.size() == genericParamsPerLevel.size() - 1);
599+
600+
// We're now going to build the type tree from the
601+
// outermost parent in, which matches the order of
602+
// the generic parameter list and genericParamsPerLevel.
603+
std::reverse(nodes.begin(), nodes.end());
604+
605+
// Walk the list of parent types together with
606+
// the generic argument list...
607+
const BoundGenericTypeRef *typeref = nullptr;
608+
auto argBegin = args.begin();
609+
for (size_t i = 0; i < nodes.size(); i++) {
610+
// Get the mangling for this node
611+
auto mangling = Demangle::mangleNode(nodes[i]);
612+
if (!mangling.isSuccess()) {
613+
return nullptr;
614+
}
626615

627-
return BoundGenericTypeRef::create(*this, mangling.result(), genericParams,
628-
parent);
616+
// Use the next N params for this node
617+
auto numGenericArgs = genericParamsPerLevel[i];
618+
// Skip nodes that don't have any actual type params.
619+
if (numGenericArgs == 0) {
620+
continue;
621+
}
622+
auto argEnd = argBegin + numGenericArgs;
623+
std::vector<const TypeRef *> params(argBegin, argEnd);
624+
argBegin = argEnd;
625+
626+
// Extend the typeref list towards the innermost type
627+
typeref = BoundGenericTypeRef::create(*this, mangling.result(), params, typeref);
628+
}
629+
return typeref;
629630
}
630631

631632
const BoundGenericTypeRef *
@@ -634,17 +635,58 @@ class TypeRefBuilder {
634635
if (!builtTypeDecl)
635636
return nullptr;
636637

637-
if (!builtTypeDecl->genericParamsPerLevel)
638+
// If there aren't generic params on the parent types, we just emit
639+
// a single BG typeref with all the generic args
640+
auto maybeGenericParamsPerLevel = builtTypeDecl->genericParamsPerLevel;
641+
if (!maybeGenericParamsPerLevel) {
638642
return BoundGenericTypeRef::create(*this, builtTypeDecl->mangledName, args, nullptr);
643+
}
639644

640-
645+
// Otherwise, work from a full demangle tree to produce a
646+
// typeref that includes information about parent generic args
641647
auto node = Dem.demangleType(builtTypeDecl->mangledName);
642-
if (!node || !node->hasChildren() || node->getKind() != Node::Kind::Type)
648+
if (!node || !node->hasChildren() || node->getKind() != Node::Kind::Type) {
649+
return nullptr;
650+
}
651+
auto startNode = node->getFirstChild();
652+
auto mangling = Demangle::mangleNode(startNode);
653+
if (!mangling.isSuccess()) {
643654
return nullptr;
655+
}
656+
657+
// Sanity: Verify that the generic params per level add
658+
// up exactly to the number of args we were provided, and
659+
// that we don't have a rediculous number of either one
660+
auto genericParamsPerLevel = *maybeGenericParamsPerLevel;
661+
if (genericParamsPerLevel.size() > 1000 || args.size() > 1000) {
662+
return nullptr;
663+
}
664+
size_t totalParams = 0;
665+
for (size_t i = 0; i < genericParamsPerLevel.size(); i++) {
666+
if (genericParamsPerLevel[i] > args.size()) {
667+
return nullptr;
668+
}
669+
totalParams += genericParamsPerLevel[i];
670+
}
671+
if (totalParams != args.size()) {
672+
return nullptr;
673+
}
644674

645-
auto type = node->getFirstChild();
646-
return createBoundGenericTypeReconstructingParent(
647-
type, *builtTypeDecl, builtTypeDecl->genericParamsPerLevel->size() - 1, args, 0);
675+
// Reconstruct all parents that have non-zero generic params
676+
auto parents = reconstructParentsOfBoundGenericType(startNode, genericParamsPerLevel, args);
677+
678+
// Collect the final set of generic params for the
679+
// innermost type. Note: This will sometimes be empty:
680+
// consider `Foo<Int, String>.Bar.Baz<Double>.Quux`
681+
// which has 2 parents in the parent list
682+
// (`Foo<Int,String>`, `Baz<Double>`), and the
683+
// startNode is `Quux` with no params.
684+
auto numGenericArgs = genericParamsPerLevel[genericParamsPerLevel.size() - 1];
685+
auto argBegin = args.end() - numGenericArgs;
686+
std::vector<const TypeRef *> params(argBegin, args.end());
687+
688+
// Build and return the top typeref
689+
return BoundGenericTypeRef::create(*this, mangling.result(), params, parents);
648690
}
649691

650692
const BoundGenericTypeRef *
Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_nested
33
// RUN: %target-codesign %t/reflect_nested
4-
// RUN: %target-run %target-swift-reflection-test %t/reflect_nested 2>&1 | %FileCheck %s --check-prefix=CHECK-%target-ptrsize
4+
// RUN: %target-run %target-swift-reflection-test %t/reflect_nested 2>&1 | %FileCheck %s --check-prefix=CHECK
55
// REQUIRES: reflection_test_support
66
// REQUIRES: executable_test
77
// UNSUPPORTED: use_os_stdlib
@@ -26,24 +26,14 @@ var obj = OuterGeneric.Inner.Innermost(x: 17, y: "hello")
2626

2727
reflect(object: obj)
2828

29-
// CHECK-64: Reflecting an object.
30-
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
31-
// CHECK-64: Type reference:
32-
// CHECK-64: (bound_generic_class reflect_nested.OuterGeneric.Inner.Innermost
33-
// CHECK-64-NEXT: (struct Swift.String)
34-
// CHECK-64-NEXT: (bound_generic_class reflect_nested.OuterGeneric.Inner
35-
// CHECK-64-NEXT: (bound_generic_class reflect_nested.OuterGeneric
36-
// CHECK-64-NEXT: (struct Swift.Int))))
29+
// CHECK: Reflecting an object.
30+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
31+
// CHECK: Type reference:
32+
// CHECK: (bound_generic_class reflect_nested.OuterGeneric.Inner.Innermost
33+
// CHECK-NEXT: (struct Swift.String)
34+
// CHECK-NEXT: (bound_generic_class reflect_nested.OuterGeneric
35+
// CHECK-NEXT: (struct Swift.Int)))
3736

38-
// CHECK-32: Reflecting an object.
39-
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
40-
// CHECK-32: Type reference:
41-
// CHECK-32: (bound_generic_class reflect_nested.OuterGeneric.Inner.Innermost
42-
// CHECK-32-NEXT: (struct Swift.String)
43-
// CHECK-32-NEXT: (bound_generic_class reflect_nested.OuterGeneric.Inner
44-
// CHECK-32-NEXT: (bound_generic_class reflect_nested.OuterGeneric
45-
// CHECK-32-NEXT: (struct Swift.Int))))
46-
4737
class OuterNonGeneric {
4838
class InnerGeneric<T, U> {
4939
var x: T
@@ -59,24 +49,13 @@ class OuterNonGeneric {
5949
var obj2 = OuterNonGeneric.InnerGeneric(x: 17, y: "hello")
6050
reflect(object: obj2)
6151

62-
// CHECK-64: Reflecting an object.
63-
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
64-
// CHECK-64: Type reference:
65-
// CHECK-64: (bound_generic_class reflect_nested.OuterNonGeneric.InnerGeneric
66-
// CHECK-64-NEXT: (struct Swift.Int)
67-
// CHECK-64-NEXT: (struct Swift.String)
68-
// CHECK-64-NEXT: (bound_generic_class reflect_nested.OuterNonGeneric))
69-
70-
// CHECK-32: Reflecting an object.
71-
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
72-
// CHECK-32: Type reference:
73-
// CHECK-32: (bound_generic_class reflect_nested.OuterNonGeneric.InnerGeneric
74-
// CHECK-32-NEXT: (struct Swift.Int)
75-
// CHECK-32-NEXT: (struct Swift.String)
76-
// CHECK-32-NEXT: (bound_generic_class reflect_nested.OuterNonGeneric))
52+
// CHECK: Reflecting an object.
53+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
54+
// CHECK: Type reference:
55+
// CHECK: (bound_generic_class reflect_nested.OuterNonGeneric.InnerGeneric
56+
// CHECK-NEXT: (struct Swift.Int)
57+
// CHECK-NEXT: (struct Swift.String))
7758

7859
doneReflecting()
7960

80-
// CHECK-64: Done.
81-
82-
// CHECK-32: Done.
61+
// CHECK: Done.

0 commit comments

Comments
 (0)