Skip to content

Commit 1398760

Browse files
authored
Merge pull request #59262 from augusto2112/nested-generic-typeref
Fix nested generic typerefs applying generic params at the wrong level
2 parents 46813f8 + 6a82edd commit 1398760

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)