Skip to content

Type reconstruction for variadic generics #63789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions include/swift/AST/ASTDemangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,16 @@ namespace Demangle {
SWIFT_BEGIN_INLINE_NAMESPACE

Type getTypeForMangling(ASTContext &ctx,
llvm::StringRef mangling);
llvm::StringRef mangling,
GenericSignature genericSig=GenericSignature());

TypeDecl *getTypeDeclForMangling(ASTContext &ctx,
llvm::StringRef mangling);
llvm::StringRef mangling,
GenericSignature genericSig=GenericSignature());

TypeDecl *getTypeDeclForUSR(ASTContext &ctx,
llvm::StringRef usr);
llvm::StringRef usr,
GenericSignature genericSig=GenericSignature());

/// An implementation of MetadataReader's BuilderType concept that
/// just finds and builds things in the AST.
Expand All @@ -55,6 +58,11 @@ class ASTBuilder {
/// Created lazily.
DeclContext *NotionalDC = nullptr;

/// The generic signature for interpreting type parameters. This is used
/// because the mangling for a type parameter doesn't record whether it
/// is a pack or not, so we have to find it here.
GenericSignature GenericSig;

public:
using BuiltType = swift::Type;
using BuiltTypeDecl = swift::GenericTypeDecl *; // nominal or type alias
Expand All @@ -66,7 +74,8 @@ class ASTBuilder {

static constexpr bool needsToPrecomputeParentGenericContextShapes = false;

explicit ASTBuilder(ASTContext &ctx) : Ctx(ctx) {}
explicit ASTBuilder(ASTContext &ctx, GenericSignature genericSig)
: Ctx(ctx), GenericSig(genericSig) {}

ASTContext &getASTContext() { return Ctx; }
DeclContext *getNotionalDC();
Expand Down Expand Up @@ -102,6 +111,12 @@ class ASTBuilder {

Type createTupleType(ArrayRef<Type> eltTypes, StringRef labels);

Type createPackType(ArrayRef<Type> eltTypes);

Type createSILPackType(ArrayRef<Type> eltTypes, bool isElementAddress);

Type createPackExpansionType(Type patternType, Type countType);

Type createFunctionType(
ArrayRef<Demangle::FunctionParam<Type>> params,
Type output, FunctionTypeFlags flags,
Expand Down
2 changes: 2 additions & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ NODE(Tuple)
NODE(TupleElement)
NODE(TupleElementName)
NODE(Pack)
NODE(SILPackDirect)
NODE(SILPackIndirect)
NODE(PackExpansion)
NODE(Type)
CONTEXT_NODE(TypeSymbolicReference)
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/Demangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ class Demangler : public NodeFactory {
NodePointer popTuple();
NodePointer popTypeList();
NodePointer popPack();
NodePointer popSILPack();
NodePointer popProtocol();
NodePointer demangleBoundGenericType();
NodePointer demangleBoundGenericArgs(NodePointer nominalType,
Expand Down
40 changes: 40 additions & 0 deletions include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,46 @@ class TypeDecoder {
return decodeMangledType(Node->getChild(0), depth + 1,
/*forRequirement=*/false);

case NodeKind::Pack:
case NodeKind::SILPackDirect:
case NodeKind::SILPackIndirect: {
llvm::SmallVector<BuiltType, 8> elements;

for (auto &element : *Node) {
// Decode the element type.
auto elementType =
decodeMangledType(element, depth + 1, /*forRequirement=*/false);
if (elementType.isError())
return elementType;

elements.push_back(elementType.getType());
}

switch (Node->getKind()) {
case NodeKind::Pack:
return Builder.createPackType(elements);
case NodeKind::SILPackDirect:
return Builder.createSILPackType(elements, /*isElementAddress=*/false);
case NodeKind::SILPackIndirect:
return Builder.createSILPackType(elements, /*isElementAddress=*/true);
default:
llvm_unreachable("Bad kind");
}
}

case NodeKind::PackExpansion: {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
"fewer children (%zu) than required (2)",
Node->getNumChildren());

auto patternType = decodeMangledType(Node->getChild(0), depth + 1);
auto countType = decodeMangledType(Node->getChild(1), depth + 1);

return Builder.createPackExpansionType(patternType.getType(),
countType.getType());
}

case NodeKind::DependentGenericType: {
if (Node->getNumChildren() < 2)
return MAKE_NODE_TYPE_ERROR(Node,
Expand Down
17 changes: 17 additions & 0 deletions include/swift/RemoteInspection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,23 @@ class TypeRefBuilder {
return TupleTypeRef::create(*this, elements, std::move(labels));
}

const TypeRef *createPackType(llvm::ArrayRef<const TypeRef *> elements) {
// FIXME: Remote mirrors support for variadic generics.
return nullptr;
}

const TypeRef *createSILPackType(llvm::ArrayRef<const TypeRef *> elements,
bool isElementAddress) {
// FIXME: Remote mirrors support for variadic generics.
return nullptr;
}

const TypeRef *createPackExpansionType(const TypeRef *patternType,
const TypeRef *countType) {
// FIXME: Remote mirrors support for variadic generics.
return nullptr;
}

const FunctionTypeRef *createFunctionType(
llvm::ArrayRef<remote::FunctionParam<const TypeRef *>> params,
const TypeRef *result, FunctionTypeFlags flags,
Expand Down
59 changes: 52 additions & 7 deletions lib/AST/ASTDemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,36 +38,39 @@
using namespace swift;

Type swift::Demangle::getTypeForMangling(ASTContext &ctx,
StringRef mangling) {
StringRef mangling,
GenericSignature genericSig) {
Demangle::Context Dem;
auto node = Dem.demangleSymbolAsNode(mangling);
if (!node)
return Type();

ASTBuilder builder(ctx);
ASTBuilder builder(ctx, genericSig);
return builder.decodeMangledType(node);
}

TypeDecl *swift::Demangle::getTypeDeclForMangling(ASTContext &ctx,
StringRef mangling) {
StringRef mangling,
GenericSignature genericSig) {
Demangle::Context Dem;
auto node = Dem.demangleSymbolAsNode(mangling);
if (!node)
return nullptr;

ASTBuilder builder(ctx);
ASTBuilder builder(ctx, genericSig);
return builder.createTypeDecl(node);
}

TypeDecl *swift::Demangle::getTypeDeclForUSR(ASTContext &ctx,
StringRef usr) {
StringRef usr,
GenericSignature genericSig) {
if (!usr.startswith("s:"))
return nullptr;

std::string mangling(usr);
mangling.replace(0, 2, MANGLING_PREFIX_STR);

return getTypeDeclForMangling(ctx, mangling);
return getTypeDeclForMangling(ctx, mangling, genericSig);
}

Type ASTBuilder::decodeMangledType(NodePointer node, bool forRequirement) {
Expand Down Expand Up @@ -341,6 +344,25 @@ Type ASTBuilder::createTupleType(ArrayRef<Type> eltTypes, StringRef labels) {
return TupleType::get(elements, Ctx);
}

Type ASTBuilder::createPackType(ArrayRef<Type> eltTypes) {
return PackType::get(Ctx, eltTypes);
}

Type ASTBuilder::createSILPackType(ArrayRef<Type> eltTypes,
bool isElementAddress) {
auto extInfo = SILPackType::ExtInfo(isElementAddress);

SmallVector<CanType, 4> elements;
for (auto eltType : eltTypes)
elements.push_back(eltType->getCanonicalType());

return SILPackType::get(Ctx, extInfo, elements);
}

Type ASTBuilder::createPackExpansionType(Type patternType, Type countType) {
return PackExpansionType::get(patternType, countType);
}

Type ASTBuilder::createFunctionType(
ArrayRef<Demangle::FunctionParam<Type>> params,
Type output, FunctionTypeFlags flags,
Expand Down Expand Up @@ -683,7 +705,23 @@ Type ASTBuilder::createMetatypeType(Type instance,

Type ASTBuilder::createGenericTypeParameterType(unsigned depth,
unsigned index) {
return GenericTypeParamType::get(/*isParameterPack*/ false, depth, index, Ctx);
// If we have a generic signature, find the parameter with the matching
// depth and index and return it, to get the correct value for the
// isParameterPack() bit.
if (GenericSig) {
for (auto paramTy : GenericSig.getGenericParams()) {
if (paramTy->getDepth() == depth && paramTy->getIndex() == index) {
return paramTy;
}
}

return Type();
}

// Otherwise, just assume we're not working with variadic generics.
// FIXME: Should we always require a generic signature in this case?
return GenericTypeParamType::get(/*isParameterPack*/ false,
depth, index, Ctx);
}

Type ASTBuilder::createDependentMemberType(StringRef member,
Expand Down Expand Up @@ -973,6 +1011,13 @@ LayoutConstraint ASTBuilder::getLayoutConstraintWithSizeAlign(
CanGenericSignature ASTBuilder::demangleGenericSignature(
NominalTypeDecl *nominalDecl,
NodePointer node) {
// The type parameters appearing in the signature's requirements are not
// notionally part of our current generic signature.
//
// FIXME: Fix this to support variadic generics.
llvm::SaveAndRestore<GenericSignature> savedSignature(
GenericSig, GenericSignature());

SmallVector<Requirement, 2> requirements;

decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
Expand Down
34 changes: 34 additions & 0 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,38 @@ NodePointer Demangler::popPack() {
return createType(Root);
}

NodePointer Demangler::popSILPack() {
NodePointer Root;

switch (nextChar()) {
case 'd':
Root = createNode(Node::Kind::SILPackDirect);
break;

case 'i':
Root = createNode(Node::Kind::SILPackIndirect);
break;

default:
return nullptr;
}

if (!popNode(Node::Kind::EmptyList)) {
bool firstElem = false;
do {
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
NodePointer Ty = popNode(Node::Kind::Type);
if (!Ty)
return nullptr;
Root->addChild(Ty, *this);
} while (!firstElem);

Root->reverseChildren();
}

return createType(Root);
}

NodePointer Demangler::popTypeList() {
NodePointer Root = createNode(Node::Kind::TypeList);

Expand Down Expand Up @@ -2364,6 +2396,8 @@ NodePointer Demangler::demangleArchetype() {
}
case 'P':
return popPack();
case 'S':
return popSILPack();
default:
return nullptr;
}
Expand Down
12 changes: 11 additions & 1 deletion lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ class NodePrinter {
case Node::Kind::Module:
case Node::Kind::Tuple:
case Node::Kind::Pack:
case Node::Kind::SILPackDirect:
case Node::Kind::SILPackIndirect:
case Node::Kind::ConstrainedExistential:
case Node::Kind::ConstrainedExistentialRequirementList:
case Node::Kind::ConstrainedExistentialSelf:
Expand Down Expand Up @@ -1511,9 +1513,17 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
Printer << "}";
return nullptr;
}
case Node::Kind::SILPackDirect:
case Node::Kind::SILPackIndirect: {
Printer << (kind == Node::Kind::SILPackDirect ? "@direct" : "@indirect");
Printer << " Pack{";
printChildren(Node, depth, ", ");
Printer << "}";
return nullptr;
}
case Node::Kind::PackExpansion: {
Printer << "repeat ";
print(Node->getChild(0), depth + 1);
Printer << "...";
return nullptr;
}
case Node::Kind::ReturnType:
Expand Down
8 changes: 8 additions & 0 deletions lib/Demangling/OldRemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1911,6 +1911,14 @@ ManglingError Remangler::manglePack(Node *node, unsigned depth) {
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}

ManglingError Remangler::mangleSILPackDirect(Node *node, unsigned depth) {
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}

ManglingError Remangler::mangleSILPackIndirect(Node *node, unsigned depth) {
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}

ManglingError Remangler::manglePackExpansion(Node *node, unsigned depth) {
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
}
Expand Down
12 changes: 12 additions & 0 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2278,6 +2278,18 @@ ManglingError Remangler::manglePack(Node *node, unsigned depth) {
return ManglingError::Success;
}

ManglingError Remangler::mangleSILPackDirect(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleTypeList(node, depth + 1));
Buffer << "QSd";
return ManglingError::Success;
}

ManglingError Remangler::mangleSILPackIndirect(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleTypeList(node, depth + 1));
Buffer << "QSi";
return ManglingError::Success;
}

ManglingError Remangler::manglePackExpansion(Node *node, unsigned depth) {
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
Buffer << "Qp";
Expand Down
6 changes: 5 additions & 1 deletion lib/IRGen/IRGenDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -907,11 +907,13 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
!Ty->getASTContext().LangOpts.EnableCXXInterop) {
// Make sure we can reconstruct mangled types for the debugger.
auto &Ctx = Ty->getASTContext();
Type Reconstructed = Demangle::getTypeForMangling(Ctx, Result);
Type Reconstructed = Demangle::getTypeForMangling(Ctx, Result, Sig);
if (!Reconstructed) {
llvm::errs() << "Failed to reconstruct type for " << Result << "\n";
llvm::errs() << "Original type:\n";
Ty->dump(llvm::errs());
if (Sig)
llvm::errs() << "Generic signature: " << Sig << "\n";
abort();
} else if (!Reconstructed->isEqual(Ty) &&
// FIXME: Some existential types are reconstructed without
Expand All @@ -924,6 +926,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
Ty->dump(llvm::errs());
llvm::errs() << "Reconstructed type:\n";
Reconstructed->dump(llvm::errs());
if (Sig)
llvm::errs() << "Generic signature: " << Sig << "\n";
abort();
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/RemoteAST/RemoteAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ class RemoteASTContextConcreteImpl final : public RemoteASTContextImpl {
public:
RemoteASTContextConcreteImpl(std::shared_ptr<MemoryReader> &&reader,
ASTContext &ctx)
: Reader(std::move(reader), ctx) {}
: Reader(std::move(reader), ctx, GenericSignature()) {}

Result<Type> getTypeForRemoteTypeMetadata(RemoteAddress metadata,
bool skipArtificial) override {
Expand Down
Loading