Skip to content

Commit 6a82edd

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 those already attached.
1 parent ed88700 commit 6a82edd

File tree

5 files changed

+229
-55
lines changed

5 files changed

+229
-55
lines changed

include/swift/AST/ASTDemangler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class ASTBuilder {
6464
using BuiltRequirement = swift::Requirement;
6565
using BuiltSubstitutionMap = swift::SubstitutionMap;
6666

67+
static constexpr bool needsToPrecomputeParentGenericContextShapes = false;
68+
6769
explicit ASTBuilder(ASTContext &ctx) : Ctx(ctx) {}
6870

6971
ASTContext &getASTContext() { return Ctx; }

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 110 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,24 @@ struct FieldTypeCollectionResult {
354354
std::vector<std::string> Errors;
355355
};
356356

357+
struct TypeRefDecl {
358+
std::string mangledName;
359+
360+
// Only used when building a bound generic typeref, and when the
361+
// generic params for all the levels are stored as a flat array.
362+
llvm::Optional<std::vector<size_t>> genericParamsPerLevel;
363+
364+
TypeRefDecl(std::string mangledName,
365+
std::vector<size_t> genericParamsPerLevel)
366+
: mangledName(mangledName),
367+
genericParamsPerLevel(genericParamsPerLevel) {}
368+
369+
TypeRefDecl(std::string mangledName)
370+
: mangledName(mangledName),
371+
genericParamsPerLevel(llvm::None) {}
372+
373+
};
374+
357375
/// An implementation of MetadataReader's BuilderType concept for
358376
/// building TypeRefs, and parsing field metadata from any images
359377
/// it has been made aware of.
@@ -366,7 +384,7 @@ class TypeRefBuilder {
366384

367385
public:
368386
using BuiltType = const TypeRef *;
369-
using BuiltTypeDecl = llvm::Optional<std::string>;
387+
using BuiltTypeDecl = llvm::Optional<TypeRefDecl>;
370388
using BuiltProtocolDecl =
371389
llvm::Optional<std::pair<std::string, bool /*isObjC*/>>;
372390
using BuiltSubstitution = std::pair<const TypeRef *, const TypeRef *>;
@@ -376,6 +394,8 @@ class TypeRefBuilder {
376394
using BuiltGenericSignature = const GenericSignatureRef *;
377395
using BuiltSubstitutionMap = llvm::DenseMap<DepthAndIndex, const TypeRef *>;
378396

397+
static constexpr bool needsToPrecomputeParentGenericContextShapes = true;
398+
379399
TypeRefBuilder(const TypeRefBuilder &other) = delete;
380400
TypeRefBuilder &operator=(const TypeRefBuilder &other) = delete;
381401

@@ -433,12 +453,30 @@ class TypeRefBuilder {
433453
return BuiltinTypeRef::create(*this, mangledName);
434454
}
435455

436-
llvm::Optional<std::string> createTypeDecl(Node *node, bool &typeAlias) {
456+
BuiltTypeDecl createTypeDecl(Node *node, std::vector<size_t> paramsPerLevel) {
457+
auto mangling = Demangle::mangleNode(node);
458+
if (!mangling.isSuccess()) {
459+
return llvm::None;
460+
}
461+
return {{mangling.result(), paramsPerLevel}};
462+
}
463+
464+
BuiltTypeDecl createTypeDecl(std::string &&mangledName,
465+
std::vector<size_t> paramsPerLevel) {
466+
return {{std::move(mangledName), {paramsPerLevel}}};
467+
}
468+
469+
BuiltTypeDecl createTypeDecl(Node *node, bool &typeAlias) {
437470
auto mangling = Demangle::mangleNode(node);
438471
if (!mangling.isSuccess()) {
439472
return llvm::None;
440473
}
441-
return mangling.result();
474+
return {{mangling.result()}};
475+
}
476+
477+
BuiltTypeDecl createTypeDecl(std::string &&mangledName,
478+
bool &typeAlias) {
479+
return {{(mangledName)}};;
442480
}
443481

444482
BuiltProtocolDecl
@@ -455,24 +493,20 @@ class TypeRefBuilder {
455493
return std::make_pair(name, true);
456494
}
457495

458-
llvm::Optional<std::string> createTypeDecl(std::string &&mangledName,
459-
bool &typeAlias) {
460-
return std::move(mangledName);
461-
}
462496

463497
const NominalTypeRef *
464-
createNominalType(const llvm::Optional<std::string> &mangledName) {
465-
return NominalTypeRef::create(*this, *mangledName, nullptr);
498+
createNominalType(const BuiltTypeDecl &typeRefDecl) {
499+
return NominalTypeRef::create(*this, typeRefDecl->mangledName, nullptr);
466500
}
467501

468502
const NominalTypeRef *
469-
createNominalType(const llvm::Optional<std::string> &mangledName,
503+
createNominalType(const BuiltTypeDecl &typeRefDecl,
470504
const TypeRef *parent) {
471-
return NominalTypeRef::create(*this, *mangledName, parent);
505+
return NominalTypeRef::create(*this, typeRefDecl->mangledName, parent);
472506
}
473507

474508
const TypeRef *
475-
createTypeAliasType(const llvm::Optional<std::string> &mangledName,
509+
createTypeAliasType(const BuiltTypeDecl &typeRefDecl,
476510
const TypeRef *parent) {
477511
// TypeRefs don't contain sugared types
478512
return nullptr;
@@ -498,17 +532,75 @@ class TypeRefBuilder {
498532
return nullptr;
499533
}
500534

535+
const BoundGenericTypeRef *createBoundGenericTypeReconstructingParent(
536+
const NodePointer node, const TypeRefDecl &decl, size_t shapeIndex,
537+
const llvm::ArrayRef<const TypeRef *> &args, size_t argsIndex) {
538+
if (!node || !node->hasChildren())
539+
return nullptr;
540+
541+
auto maybeGenericParamsPerLevel = decl.genericParamsPerLevel;
542+
if (!maybeGenericParamsPerLevel)
543+
return nullptr;
544+
545+
auto genericParamsPerLevel = *maybeGenericParamsPerLevel;
546+
547+
auto kind = node->getKind();
548+
// Kinds who have a "BoundGeneric..." variant.
549+
if (kind != Node::Kind::Class && kind != Node::Kind::Structure &&
550+
kind != Node::Kind::Enum && kind != Node::Kind::Protocol &&
551+
kind != Node::Kind::OtherNominalType && kind != Node::Kind::TypeAlias &&
552+
kind != Node::Kind::Function)
553+
return nullptr;
554+
auto mangling = Demangle::mangleNode(node);
555+
if (!mangling.isSuccess())
556+
return nullptr;
557+
558+
auto numGenericArgs = genericParamsPerLevel[shapeIndex];
559+
560+
std::vector<const TypeRef *> genericParams(
561+
args.end() - argsIndex - numGenericArgs, args.end() - argsIndex);
562+
563+
const BoundGenericTypeRef *parent = nullptr;
564+
if (node->hasChildren())
565+
parent = createBoundGenericTypeReconstructingParent(
566+
node->getFirstChild(), decl, --shapeIndex, args, argsIndex + numGenericArgs);
567+
568+
return BoundGenericTypeRef::create(*this, mangling.result(), genericParams,
569+
parent);
570+
}
571+
501572
const BoundGenericTypeRef *
502-
createBoundGenericType(const llvm::Optional<std::string> &mangledName,
503-
const std::vector<const TypeRef *> &args) {
504-
return BoundGenericTypeRef::create(*this, *mangledName, args, nullptr);
573+
createBoundGenericType(const BuiltTypeDecl &builtTypeDecl,
574+
const llvm::ArrayRef<const TypeRef *> &args) {
575+
if (!builtTypeDecl)
576+
return nullptr;
577+
578+
if (!builtTypeDecl->genericParamsPerLevel)
579+
return BoundGenericTypeRef::create(*this, builtTypeDecl->mangledName, args, nullptr);
580+
581+
582+
auto node = Dem.demangleType(builtTypeDecl->mangledName);
583+
if (!node || !node->hasChildren() || node->getKind() != Node::Kind::Type)
584+
return nullptr;
585+
586+
auto type = node->getFirstChild();
587+
return createBoundGenericTypeReconstructingParent(
588+
type, *builtTypeDecl, builtTypeDecl->genericParamsPerLevel->size() - 1, args, 0);
505589
}
506590

507591
const BoundGenericTypeRef *
508-
createBoundGenericType(const llvm::Optional<std::string> &mangledName,
592+
createBoundGenericType(const BuiltTypeDecl &builtTypeDecl,
509593
llvm::ArrayRef<const TypeRef *> args,
510594
const TypeRef *parent) {
511-
return BoundGenericTypeRef::create(*this, *mangledName, args, parent);
595+
if (!builtTypeDecl)
596+
return nullptr;
597+
598+
if (!builtTypeDecl->genericParamsPerLevel)
599+
return BoundGenericTypeRef::create(*this, builtTypeDecl->mangledName, args,
600+
parent);
601+
assert(parent == nullptr &&
602+
"Parent is not null but we're reconstructing the parent!");
603+
return createBoundGenericType(builtTypeDecl, args);
512604
}
513605

514606
const TypeRef *
@@ -627,7 +719,7 @@ class TypeRefBuilder {
627719
if (protocol->second) {
628720
return llvm::cast<TypeRef>(createObjCProtocolType(protocol->first));
629721
} else {
630-
return llvm::cast<TypeRef>(createNominalType(protocol->first));
722+
return llvm::cast<TypeRef>(createNominalType(TypeRefDecl(protocol->first)));
631723
}
632724
}
633725

include/swift/Remote/MetadataReader.h

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
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

@@ -2818,8 +2819,14 @@ class MetadataReader {
28182819

28192820
/// Given a read nominal type descriptor, attempt to build a
28202821
/// nominal type decl from it.
2821-
BuiltTypeDecl
2822-
buildNominalTypeDecl(ContextDescriptorRef descriptor) {
2822+
template <
2823+
typename T = BuilderType,
2824+
typename std::enable_if_t<
2825+
!std::is_same<
2826+
bool,
2827+
decltype(T::needsToPrecomputeParentGenericContextShapes)>::value,
2828+
bool> = true>
2829+
BuiltTypeDecl buildNominalTypeDecl(ContextDescriptorRef descriptor) {
28232830
// Build the demangling tree from the context tree.
28242831
Demangler dem;
28252832
auto node = buildContextMangling(descriptor, dem);
@@ -2830,6 +2837,41 @@ class MetadataReader {
28302837
return decl;
28312838
}
28322839

2840+
template <
2841+
typename T = BuilderType,
2842+
typename std::enable_if_t<
2843+
std::is_same<
2844+
bool,
2845+
decltype(T::needsToPrecomputeParentGenericContextShapes)>::value,
2846+
bool> = true>
2847+
BuiltTypeDecl buildNominalTypeDecl(ContextDescriptorRef descriptor) {
2848+
// Build the demangling tree from the context tree.
2849+
Demangler dem;
2850+
auto node = buildContextMangling(descriptor, dem);
2851+
if (!node || node->getKind() != Node::Kind::Type)
2852+
return BuiltTypeDecl();
2853+
std::vector<size_t> paramsPerLevel;
2854+
size_t runningCount = 0;
2855+
std::function<void(ContextDescriptorRef current, size_t &)> countLevels =
2856+
[&](ContextDescriptorRef current, size_t &runningCount) {
2857+
if (auto parentContextRef = readParentContextDescriptor(current))
2858+
if (parentContextRef->isResolved())
2859+
if (auto parentContext = parentContextRef->getResolved())
2860+
countLevels(parentContext, runningCount);
2861+
2862+
auto genericContext = current->getGenericContext();
2863+
if (!genericContext)
2864+
return;
2865+
auto contextHeader = genericContext->getGenericContextHeader();
2866+
2867+
paramsPerLevel.emplace_back(contextHeader.NumParams - runningCount);
2868+
runningCount += paramsPerLevel.back();
2869+
};
2870+
countLevels(descriptor, runningCount);
2871+
BuiltTypeDecl decl = Builder.createTypeDecl(node, paramsPerLevel);
2872+
return decl;
2873+
}
2874+
28332875
#if SWIFT_OBJC_INTEROP
28342876
std::string readObjCProtocolName(StoredPointer Address) {
28352877
auto Size = sizeof(TargetObjCProtocolPrefix<Runtime>);

stdlib/public/Reflection/TypeRef.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,8 +579,35 @@ class DemanglingForTypeRef
579579
genericNode->addChild(unspecializedType, Dem);
580580
genericNode->addChild(genericArgsList, Dem);
581581

582-
if (auto parent = BG->getParent())
583-
assert(false && "not implemented");
582+
auto parent = BG->getParent();
583+
if (!parent)
584+
return genericNode;
585+
586+
auto parentNode = visit(parent);
587+
if (!parentNode || !parentNode->hasChildren() ||
588+
parentNode->getKind() != Node::Kind::Type ||
589+
!unspecializedType->hasChildren())
590+
return genericNode;
591+
592+
// Peel off the "Type" node.
593+
parentNode = parentNode->getFirstChild();
594+
595+
auto nominalNode = unspecializedType->getFirstChild();
596+
597+
if (nominalNode->getNumChildren() != 2)
598+
return genericNode;
599+
600+
// Save identifier for reinsertion later, we have to remove it
601+
// so we can insert the parent node as the first child.
602+
auto identifierNode = nominalNode->getLastChild();
603+
604+
// Remove all children.
605+
nominalNode->removeChildAt(1);
606+
nominalNode->removeChildAt(0);
607+
608+
// Add the parent we just visited back in, followed by the identifier.
609+
nominalNode->addChild(parentNode, Dem);
610+
nominalNode->addChild(identifierNode, Dem);
584611

585612
return genericNode;
586613
}

0 commit comments

Comments
 (0)