Skip to content

Commit 488fb82

Browse files
committed
Refactor to handle the parent list separately
Handle the top node directly in `createBoundGenericType` so that we can be sure to always include it regardless of whether it has direct generic type params or not. The helper function can now focus only on handling parents (where we must only include ones that actually contain generic type params). This separates the two different cases and makes it a little easier to follow. I refactored `reconstructParentsOfBoundGenericType` to be iterative rather than recursive, though I'm not sure that really matters.
1 parent 5350cd5 commit 488fb82

File tree

1 file changed

+47
-41
lines changed

1 file changed

+47
-41
lines changed

include/swift/RemoteInspection/TypeRefBuilder.h

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -570,16 +570,15 @@ class TypeRefBuilder {
570570
// Construct a bound generic type ref along with the parent type info
571571
// The parent list contains every parent type with at least 1 generic
572572
// type parameter.
573-
const BoundGenericTypeRef *createBoundGenericTypeReconstructingParent(
573+
const BoundGenericTypeRef *reconstructParentsOfBoundGenericType(
574574
const NodePointer startNode,
575575
const std::vector<size_t> &genericParamsPerLevel,
576576
const llvm::ArrayRef<const TypeRef *> &args)
577577
{
578-
// Collect all the relevant nodes, including the current node
578+
// Collect the first N parents that potentially have generic args
579+
// (Ignore the last genericParamPerLevel, which
580+
// applies to the startNode itself.)
579581
std::vector<NodePointer> nodes;
580-
581-
// Iterate our parents, collecting the first N parents
582-
// that potentially have generic args
583582
NodePointer node = startNode;
584583
while (nodes.size() < genericParamsPerLevel.size() - 1) {
585584
if (!node || !node->hasChildren()) {
@@ -607,7 +606,6 @@ class TypeRefBuilder {
607606
// the generic argument list...
608607
const BoundGenericTypeRef *typeref = nullptr;
609608
auto argBegin = args.begin();
610-
size_t totalArgs = 0;
611609
for (size_t i = 0; i < nodes.size(); i++) {
612610
// Get the mangling for this node
613611
auto mangling = Demangle::mangleNode(nodes[i]);
@@ -621,41 +619,14 @@ class TypeRefBuilder {
621619
if (numGenericArgs == 0) {
622620
continue;
623621
}
624-
if (numGenericArgs > args.size() || totalArgs + numGenericArgs > args.size()) {
625-
return nullptr;
626-
}
627622
auto argEnd = argBegin + numGenericArgs;
628-
totalArgs += numGenericArgs;
629623
std::vector<const TypeRef *> params(argBegin, argEnd);
630624
argBegin = argEnd;
631625

632-
// Extend the typeref up one level
626+
// Extend the typeref list towards the innermost type
633627
typeref = BoundGenericTypeRef::create(*this, mangling.result(), params, typeref);
634628
}
635-
636-
// Now let's stack the startNode on top of the parent list
637-
// to obtain the final full typeref:
638-
auto mangling = Demangle::mangleNode(startNode);
639-
if (!mangling.isSuccess()) {
640-
return nullptr;
641-
}
642-
643-
// Collect the final set of generic params for the
644-
// startNode. Note: This will sometimes be empty:
645-
// consider `Foo<Int, String>.Bar.Baz<Double>.Quux`
646-
// which has 2 parents in the parent list
647-
// (`Foo<Int,String>`, `Baz<Double>`), and the
648-
// startNode is `Quux` with no params.
649-
auto numGenericArgs = genericParamsPerLevel[genericParamsPerLevel.size() - 1];
650-
auto argEnd = argBegin + numGenericArgs;
651-
if (argEnd != args.end()) {
652-
// This node should exactly consume the remaining args
653-
return nullptr;
654-
}
655-
std::vector<const TypeRef *> params(argBegin, argEnd);
656-
657-
// Build and return the top typeref
658-
return BoundGenericTypeRef::create(*this, mangling.result(), params, typeref);
629+
return typeref;
659630
}
660631

661632
const BoundGenericTypeRef *
@@ -672,15 +643,50 @@ class TypeRefBuilder {
672643
}
673644

674645
// Otherwise, work from a full demangle tree to produce a
675-
// typeref that includes all parents that have generic params
646+
// typeref that includes information about parent generic args
676647
auto node = Dem.demangleType(builtTypeDecl->mangledName);
677-
if (node && node->hasChildren() && node->getKind() == Node::Kind::Type) {
678-
auto type = node->getFirstChild();
679-
auto genericParamsPerLevel = *maybeGenericParamsPerLevel;
680-
return createBoundGenericTypeReconstructingParent(type, genericParamsPerLevel, args);
681-
} else {
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()) {
654+
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()) {
682672
return nullptr;
683673
}
674+
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);
684690
}
685691

686692
const BoundGenericTypeRef *

0 commit comments

Comments
 (0)