diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h index 36ddfd841e23b..77bb3bc6ccd8e 100644 --- a/include/swift/Demangling/TypeDecoder.h +++ b/include/swift/Demangling/TypeDecoder.h @@ -573,6 +573,43 @@ void decodeRequirement( } } +/// Extract the protocol and requirement nodes from a shape symbol. +static inline std::pair +decodeShape(NodePointer Node) { + if (!Node || Node->getKind() != Node::Kind::Global || + Node->getNumChildren() != 1) + return {nullptr, nullptr}; + Node = Node->getChild(0); + if (Node && (Node->getKind() == Node::Kind::Uniquable) && + Node->getNumChildren() == 1) + Node = Node->getChild(0); + if (!Node || Node->getKind() != Node::Kind::ExtendedExistentialTypeShape || + Node->getNumChildren() != 2) + return {nullptr, nullptr}; + Node = Node->getChild(1); + if (!Node || Node->getKind() != Node::Kind::Type || + Node->getNumChildren() != 1) + return {nullptr, nullptr}; + Node = Node->getChild(0); + if (!Node || Node->getKind() != Node::Kind::ConstrainedExistential || + Node->getNumChildren() != 2) + return {nullptr, nullptr}; + NodePointer Requirements = Node->getChild(1); + if (!Requirements || Requirements->getKind() != + Node::Kind::ConstrainedExistentialRequirementList) + return {nullptr, nullptr}; + + Node = Node->getChild(0); + if (!Node || Node->getKind() != Node::Kind::Type || + Node->getNumChildren() != 1) + return {nullptr, nullptr}; + NodePointer Protocol = Node; + if (!Protocol) + return {nullptr, nullptr}; + + return {Protocol, Requirements}; +} + #define MAKE_NODE_TYPE_ERROR(Node, Fmt, ...) \ TYPE_LOOKUP_ERROR_FMT("TypeDecoder.h:%u: Node kind %u \"%.*s\" - " Fmt, \ __LINE__, (unsigned)Node->getKind(), \ diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index ee4dc8e0cdc16..ee94c67d6ca7f 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -509,8 +509,8 @@ class MetadataReader { // The symbolic reference points at a non-unique extended // existential type shape. return dem.createNode( - Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference, - resolved.getResolvedAddress().getAddressData()); + Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference, + resolved.getResolvedAddress().getAddressData()); } case Demangle::SymbolicReferenceKind::ObjectiveCProtocol: { // 'resolved' points to a struct of two relative addresses. @@ -886,6 +886,74 @@ class MetadataReader { return resolver.swiftProtocol(Demangled); } + BuiltType readTypeFromShape( + RemoteAbsolutePointer shapeAddress, + std::function>(unsigned)> getArgs) { + StoredPointer addr = shapeAddress.getResolvedAddress().getAddressData(); + ShapeRef Shape = readShape(addr); + if (!Shape) + return BuiltType(); + + assert(Shape->hasGeneralizationSignature()); + auto builtArgs = getArgs(Shape->getGenSigArgumentLayoutSizeInWords()); + + // Pull out the existential type from the mangled type name. + Demangler dem; + auto mangledExistentialAddr = + resolveRelativeField(Shape, Shape->ExistentialType); + auto node = readMangledName(RemoteAddress(mangledExistentialAddr), + MangledNameKind::Type, dem); + if (!node) + return BuiltType(); + + BuiltType builtProto = decodeMangledType(node).getType(); + if (!builtProto) + return BuiltType(); + + if (builtArgs) { + // Build up a substitution map for the generalized signature. + BuiltGenericSignature sig = + decodeRuntimeGenericSignature(Shape, + Shape->getGeneralizationSignature()) + .getType(); + if (!sig) + return BuiltType(); + + BuiltSubstitutionMap subst = + Builder.createSubstitutionMap(sig, *builtArgs); + if (subst.empty()) + return BuiltType(); + + builtProto = Builder.subst(builtProto, subst); + if (!builtProto) + return BuiltType(); + } + + // Read the type expression to build up any remaining layers of + // existential metatype. + if (Shape->Flags.hasTypeExpression()) { + Demangler dem; + + // Read the mangled name. + auto mangledContextName = Shape->getTypeExpression(); + auto mangledNameAddress = + resolveRelativeField(Shape, mangledContextName->name); + auto node = readMangledName(RemoteAddress(mangledNameAddress), + MangledNameKind::Type, dem); + if (!node) + return BuiltType(); + + while (node->getKind() == Demangle::Node::Kind::Type && + node->getNumChildren() && + node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype && + node->getChild(0)->getNumChildren()) { + builtProto = Builder.createExistentialMetatypeType(builtProto); + node = node->getChild(0)->getChild(0); + } + } + return builtProto; + } + /// Given a remote pointer to metadata, attempt to turn it into a type. BuiltType readTypeFromMetadata(StoredPointer MetadataAddress, @@ -1081,79 +1149,25 @@ class MetadataReader { } case MetadataKind::ExtendedExistential: { auto Exist = cast>(Meta); - // Read the shape for this existential. StoredPointer shapeAddress = stripSignedPointer(Exist->Shape); - ShapeRef Shape = readShape(shapeAddress); - if (!Shape) - return BuiltType(); - - const unsigned shapeArgumentCount - = Shape->getGenSigArgumentLayoutSizeInWords(); - // Pull out the arguments to the generalization signature. - assert(Shape->hasGeneralizationSignature()); - std::vector builtArgs; - for (unsigned i = 0; i < shapeArgumentCount; ++i) { - auto remoteArg = Exist->getGeneralizationArguments()[i]; - auto builtArg = readTypeFromMetadata(remoteArg, false, recursion_limit); - if (!builtArg) - return BuiltType(); - builtArgs.push_back(builtArg); - } - - // Pull out the existential type from the mangled type name. - Demangler dem; - auto mangledExistentialAddr = - resolveRelativeField(Shape, Shape->ExistentialType); - auto node = readMangledName(RemoteAddress(mangledExistentialAddr), - MangledNameKind::Type, dem); - if (!node) - return BuiltType(); - - BuiltType builtProto = decodeMangledType(node).getType(); - if (!builtProto) - return BuiltType(); - - // Build up a substitution map for the generalized signature. - BuiltGenericSignature sig = - decodeRuntimeGenericSignature(Shape, - Shape->getGeneralizationSignature()) - .getType(); - if (!sig) - return BuiltType(); - - BuiltSubstitutionMap subst = - Builder.createSubstitutionMap(sig, builtArgs); - if (subst.empty()) - return BuiltType(); - - builtProto = Builder.subst(builtProto, subst); - if (!builtProto) - return BuiltType(); - - // Read the type expression to build up any remaining layers of - // existential metatype. - if (Shape->Flags.hasTypeExpression()) { - Demangler dem; - - // Read the mangled name. - auto mangledContextName = Shape->getTypeExpression(); - auto mangledNameAddress = - resolveRelativeField(Shape, mangledContextName->name); - auto node = readMangledName(RemoteAddress(mangledNameAddress), - MangledNameKind::Type, dem); - if (!node) - return BuiltType(); - - while (node->getKind() == Demangle::Node::Kind::Type && - node->getNumChildren() && - node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype && - node->getChild(0)->getNumChildren()) { - builtProto = Builder.createExistentialMetatypeType(builtProto); - node = node->getChild(0)->getChild(0); - } - } + auto builtProto = readTypeFromShape( + RemoteAddress(shapeAddress), + [&](unsigned shapeArgumentCount) + -> std::optional> { + // Pull out the arguments to the generalization signature. + std::vector builtArgs; + for (unsigned i = 0; i < shapeArgumentCount; ++i) { + auto remoteArg = Exist->getGeneralizationArguments()[i]; + auto builtArg = + readTypeFromMetadata(remoteArg, false, recursion_limit); + if (!builtArg) + return std::nullopt; + builtArgs.push_back(builtArg); + } + return builtArgs; + }); TypeCache[TypeCacheKey] = builtProto; return builtProto; } @@ -1366,69 +1380,60 @@ class MetadataReader { if (address.getOffset() == 0) return ParentContextDescriptorRef(address.getSymbol()); } - + return ParentContextDescriptorRef( - readContextDescriptor(address.getResolvedAddress().getAddressData())); + readContextDescriptor(address.getResolvedAddress().getAddressData())); } - ShapeRef - readShape(StoredPointer address) { + ShapeRef readShape(StoredPointer address) { if (address == 0) return nullptr; + using ShapeHeader = TargetExtendedExistentialTypeShape; auto cached = ShapeCache.find(address); if (cached != ShapeCache.end()) - return ShapeRef(address, - reinterpret_cast *>( - cached->second.get())); - - ExtendedExistentialTypeShapeFlags flags; - if (!Reader->readBytes(RemoteAddress(address), (uint8_t*)&flags, - sizeof(flags))) - return nullptr; + return ShapeRef( + address, reinterpret_cast(cached->second.get())); - // Read the size of the requirement signature. - uint64_t reqSigGenericSize = 0; - uint64_t genericHeaderSize = sizeof(GenericContextDescriptorHeader); + uint64_t descriptorSize; { - GenericContextDescriptorHeader header; - auto headerAddr = address + sizeof(flags); - - if (!Reader->readBytes(RemoteAddress(headerAddr), - (uint8_t*)&header, sizeof(header))) + auto readResult = + Reader->readBytes(RemoteAddress(address), sizeof(ShapeHeader)); + if (!readResult) return nullptr; - - reqSigGenericSize = reqSigGenericSize - + (header.NumParams + 3u & ~3u) - + header.NumRequirements - * sizeof(TargetGenericRequirementDescriptor); - } - uint64_t typeExprSize = flags.hasTypeExpression() ? sizeof(StoredPointer) : 0; - uint64_t suggestedVWSize = flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0; - - uint64_t size = sizeof(ExtendedExistentialTypeShapeFlags) + - sizeof(TargetRelativeDirectPointer) + - genericHeaderSize + typeExprSize + suggestedVWSize + - reqSigGenericSize; - if (size > MaxMetadataSize) + auto shapeHeader = + reinterpret_cast(readResult.get()); + + // Read the size of the requirement signature. + uint64_t reqSigGenericSize = 0; + auto flags = shapeHeader->Flags; + auto &reqSigHeader = shapeHeader->ReqSigHeader; + reqSigGenericSize = + reqSigGenericSize + (reqSigHeader.NumParams + 3u & ~3u) + + reqSigHeader.NumRequirements * + sizeof(TargetGenericRequirementDescriptor); + uint64_t typeExprSize = + flags.hasTypeExpression() ? sizeof(StoredPointer) : 0; + uint64_t suggestedVWSize = + flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0; + + descriptorSize = sizeof(shapeHeader) + typeExprSize + suggestedVWSize + + reqSigGenericSize; + } + if (descriptorSize > MaxMetadataSize) return nullptr; - auto readResult = Reader->readBytes(RemoteAddress(address), size); + auto readResult = Reader->readBytes(RemoteAddress(address), descriptorSize); if (!readResult) return nullptr; - auto descriptor = - reinterpret_cast *>( - readResult.get()); + auto descriptor = reinterpret_cast(readResult.get()); - ShapeCache.insert( - std::make_pair(address, std::move(readResult))); + ShapeCache.insert(std::make_pair(address, std::move(readResult))); return ShapeRef(address, descriptor); } /// Given the address of a context descriptor, attempt to read it. - ContextDescriptorRef - readContextDescriptor(StoredPointer address) { + ContextDescriptorRef readContextDescriptor(StoredPointer address) { if (address == 0) return nullptr; diff --git a/include/swift/RemoteInspection/TypeRef.h b/include/swift/RemoteInspection/TypeRef.h index 51093b9acc17f..354492a497b79 100644 --- a/include/swift/RemoteInspection/TypeRef.h +++ b/include/swift/RemoteInspection/TypeRef.h @@ -731,6 +731,64 @@ class ConstrainedExistentialTypeRef final : public TypeRef { } }; +class SymbolicExtendedExistentialTypeRef final : public TypeRef { + const ProtocolCompositionTypeRef *Protocol; + std::vector Requirements; + std::vector Arguments; + ExtendedExistentialTypeShapeFlags Flags; + + static TypeRefID Profile(const ProtocolCompositionTypeRef *Protocol, + llvm::ArrayRef Requirements, + llvm::ArrayRef Arguments, + ExtendedExistentialTypeShapeFlags Flags) { + TypeRefID ID; + ID.addPointer(Protocol); + for (auto reqt : Requirements) { + ID.addPointer(reqt.getFirstType()); + if (reqt.getKind() != RequirementKind::Layout) + ID.addPointer(reqt.getSecondType()); + else + ID.addInteger( + unsigned(0)); // FIXME: Layout constraints aren't implemented yet + ID.addInteger(unsigned(reqt.getKind())); + } + + for (auto &Arg : Arguments) + ID.addPointer(Arg); + return ID; + } + +public: + SymbolicExtendedExistentialTypeRef( + const ProtocolCompositionTypeRef *Protocol, + llvm::ArrayRef Requirements, + llvm::ArrayRef Args, + ExtendedExistentialTypeShapeFlags Flags) + : TypeRef(TypeRefKind::SymbolicExtendedExistential), Protocol(Protocol), + Requirements(Requirements), Arguments(Args), Flags(Flags) {} + + template + static const SymbolicExtendedExistentialTypeRef * + create(Allocator &A, const ProtocolCompositionTypeRef *Protocol, + llvm::ArrayRef Requirements, + llvm::ArrayRef Args, + ExtendedExistentialTypeShapeFlags Flags) { + FIND_OR_CREATE_TYPEREF(A, SymbolicExtendedExistentialTypeRef, Protocol, + Requirements, Args, Flags); + } + + const ProtocolCompositionTypeRef *getProtocol() const { return Protocol; } + llvm::ArrayRef getRequirements() const { + return Requirements; + } + llvm::ArrayRef getArguments() const { return Arguments; } + ExtendedExistentialTypeShapeFlags getFlags() const { return Flags; } + + static bool classof(const TypeRef *TR) { + return TR->getKind() == TypeRefKind::SymbolicExtendedExistential; + } +}; + class MetatypeTypeRef final : public TypeRef { const TypeRef *InstanceType; bool WasAbstract; diff --git a/include/swift/RemoteInspection/TypeRefBuilder.h b/include/swift/RemoteInspection/TypeRefBuilder.h index 960536977a9a1..0b8629d36f2bc 100644 --- a/include/swift/RemoteInspection/TypeRefBuilder.h +++ b/include/swift/RemoteInspection/TypeRefBuilder.h @@ -1283,8 +1283,26 @@ class TypeRefBuilder { const TypeRef * createSymbolicExtendedExistentialType(NodePointer shapeNode, llvm::ArrayRef args) { - // Can't handle this here. - return nullptr; + // Non-unique shape symbols start with an offset to a cache variable, right + // before the shape. Metadata pointers point directly to the shape, but when + // reading from a shape symbol, this needs to be corrected. + uint32_t offset = 0; + if (shapeNode->getKind() == + Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference) + offset = sizeof(uint32_t); + remote::RemoteAddress shape(shapeNode->getIndex() + offset); + + return OpaqueShapeReader( + shape, + [&](unsigned shapeArgumentCount) + -> std::optional> { + if (args.size() != shapeArgumentCount) + return std::nullopt; + if (llvm::any_of( + args, [](const TypeRef *arg) { return !arg->isConcrete(); })) + return std::nullopt; + return args; + }); } const ExistentialMetatypeTypeRef *createExistentialMetatypeType( @@ -1312,8 +1330,7 @@ class TypeRefBuilder { const DependentMemberTypeRef * createDependentMemberType(const std::string &member, const TypeRef *base) { - // Should not have unresolved dependent member types here. - return nullptr; + return DependentMemberTypeRef::create(*this, member, base, ""); } const DependentMemberTypeRef * @@ -1479,6 +1496,13 @@ class TypeRefBuilder { using PointerReader = std::function( remote::RemoteAddress, unsigned)>; + using ShapeReader = std::function>(unsigned)>)>; + + using PointerSymbolResolver = + std::function( + remote::RemoteAddress)>; using DynamicSymbolResolver = std::function( remote::RemoteAddress)>; @@ -1511,6 +1535,8 @@ class TypeRefBuilder { ByteReader OpaqueByteReader; StringReader OpaqueStringReader; PointerReader OpaquePointerReader; + ShapeReader OpaqueShapeReader; + PointerSymbolResolver OpaquePointerSymbolResolver; DynamicSymbolResolver OpaqueDynamicSymbolResolver; IntVariableReader OpaqueIntVariableReader; @@ -1549,6 +1575,18 @@ class TypeRefBuilder { -> std::optional { return reader.Reader->readPointer(address, size); }), + OpaqueShapeReader( + [&reader](remote::RemoteAbsolutePointer pointer, + std::function>( + unsigned)> + getArgs) -> const TypeRef * { + return reader.readTypeFromShape(pointer, getArgs); + }), + OpaquePointerSymbolResolver( + [&reader](remote::RemoteAddress address) + -> std::optional { + return reader.Reader->resolvePointerAsSymbol(address); + }), OpaqueDynamicSymbolResolver( [&reader](remote::RemoteAddress address) -> std::optional { diff --git a/include/swift/RemoteInspection/TypeRefs.def b/include/swift/RemoteInspection/TypeRefs.def index 353987794ee15..0fcd992999741 100644 --- a/include/swift/RemoteInspection/TypeRefs.def +++ b/include/swift/RemoteInspection/TypeRefs.def @@ -23,6 +23,7 @@ TYPEREF(Tuple, TypeRef) TYPEREF(Function, TypeRef) TYPEREF(ProtocolComposition, TypeRef) TYPEREF(ConstrainedExistential, TypeRef) +TYPEREF(SymbolicExtendedExistential, TypeRef) TYPEREF(Metatype, TypeRef) TYPEREF(ExistentialMetatype, TypeRef) TYPEREF(GenericTypeParameter, TypeRef) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index d3bc9b57b5366..1bd39d382ef50 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -792,7 +792,9 @@ Type ASTBuilder::createConstrainedExistentialType( if (auto *memberTy = req.getFirstType()->getAs()) { if (memberTy->getBase()->is()) { // This is the only case we understand so far. - primaryAssociatedTypes[memberTy->getAssocType()] = req.getSecondType(); + if (auto *assocTy = memberTy->getAssocType()) + primaryAssociatedTypes[assocTy] = req.getSecondType(); + continue; } } @@ -810,10 +812,11 @@ Type ASTBuilder::createConstrainedExistentialType( llvm::SmallVector args; for (auto *assocTy : proto->getPrimaryAssociatedTypes()) { auto found = primaryAssociatedTypes.find(assocTy); - if (found == primaryAssociatedTypes.end()) - return protoTy; - args.push_back(found->second); - claimed.insert(found->first); + if (found != primaryAssociatedTypes.end()) { + args.push_back(found->second); + claimed.insert(found->first); + continue; + } } // We may not have any arguments because the constrained existential is a diff --git a/stdlib/public/RemoteInspection/TypeLowering.cpp b/stdlib/public/RemoteInspection/TypeLowering.cpp index fdc3273aaccae..ad9e5c9bf8dd2 100644 --- a/stdlib/public/RemoteInspection/TypeLowering.cpp +++ b/stdlib/public/RemoteInspection/TypeLowering.cpp @@ -1154,6 +1154,7 @@ class ExistentialTypeInfoBuilder { TypeConverter &TC; std::vector Protocols; const TypeRef *Superclass = nullptr; + remote::RemoteAbsolutePointer Shape; ExistentialTypeRepresentation Representation; ReferenceCounting Refcounting; bool ObjC; @@ -1321,6 +1322,24 @@ class ExistentialTypeInfoBuilder { Representation = ExistentialTypeRepresentation::Class; } + void addShape(const ProtocolCompositionTypeRef *Protocol, + ExtendedExistentialTypeShapeFlags Flags) { + switch (Flags.getSpecialKind()) { + case ExtendedExistentialTypeShapeFlags::SpecialKind::Class: + Representation = ExistentialTypeRepresentation::Class; + break; + case ExtendedExistentialTypeShapeFlags::SpecialKind::Metatype: + case ExtendedExistentialTypeShapeFlags::SpecialKind::ExplicitLayout: + case ExtendedExistentialTypeShapeFlags::SpecialKind::None: + Representation = ExistentialTypeRepresentation::Opaque; + break; + } + + if (Protocol) + for (auto *Protocol : Protocol->getProtocols()) + addProtocol(Protocol); + } + const TypeInfo *build(remote::TypeInfoProvider *ExternalTypeInfo) { examineProtocols(); @@ -1780,6 +1799,11 @@ class HasFixedSize return true; } + bool visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + return true; + } + bool visitSILBoxTypeRef(const SILBoxTypeRef *SB) { return true; @@ -1923,6 +1947,11 @@ class HasSingletonMetatype return MetatypeRepresentation::Thin; } + MetatypeRepresentation visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + return MetatypeRepresentation::Thin; + } + MetatypeRepresentation visitMetatypeTypeRef(const MetatypeTypeRef *M) { if (M->wasAbstract()) return MetatypeRepresentation::Thick; @@ -2520,6 +2549,13 @@ class LowerType return builder.buildMetatype(ExternalTypeInfo); } + const TypeInfo *visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + ExistentialTypeInfoBuilder builder(TC); + builder.addShape(SEET->getProtocol(), SEET->getFlags()); + return builder.build(ExternalTypeInfo); + } + const TypeInfo * visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) { DEBUG_LOG(fprintf(stderr, "Unresolved generic TypeRef: "); GTP->dump()); diff --git a/stdlib/public/RemoteInspection/TypeRef.cpp b/stdlib/public/RemoteInspection/TypeRef.cpp index 6ea89e624fdcb..0c97ccb770153 100644 --- a/stdlib/public/RemoteInspection/TypeRef.cpp +++ b/stdlib/public/RemoteInspection/TypeRef.cpp @@ -289,6 +289,15 @@ class PrintTypeRef : public TypeRefVisitor { stream << ")"; } + void visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *CET) { + printHeader("symbolic_extended_existential_type"); + printRec(CET->getProtocol()); + for (auto &arg : CET->getArguments()) + printRec(arg); + stream << ")"; + } + void visitMetatypeTypeRef(const MetatypeTypeRef *M) { printHeader("metatype"); if (M->wasAbstract()) @@ -513,6 +522,15 @@ struct TypeRefIsConcrete return visit(CET->getBase()); } + bool visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + visit(SEET->getProtocol()); + for (auto &Arg : SEET->getArguments()) + if (!visit(Arg)) + return false; + return true; + } + bool visitMetatypeTypeRef(const MetatypeTypeRef *M) { return visit(M->getInstanceType()); } @@ -952,6 +970,19 @@ class DemanglingForTypeRef return node; } + Demangle::NodePointer visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + auto node = Dem.createNode(Node::Kind::ConstrainedExistential); + node->addChild(visit(SEET->getProtocol()), Dem); + auto constraintList = + Dem.createNode(Node::Kind::ConstrainedExistentialRequirementList); + for (auto req : SEET->getRequirements()) + constraintList->addChild(visitTypeRefRequirement(req), Dem); + node->addChild(constraintList, Dem); + // FIXME: This is lossy. We're dropping the Arguments here. + return node; + } + Demangle::NodePointer visitMetatypeTypeRef(const MetatypeTypeRef *M) { auto node = Dem.createNode(Node::Kind::Metatype); // FIXME: This is lossy. @objc_metatype is also abstract. @@ -1354,6 +1385,11 @@ class ThickenMetatype CET->getRequirements()); } + const TypeRef *visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + return SEET; + } + const TypeRef *visitMetatypeTypeRef(const MetatypeTypeRef *M) { return MetatypeTypeRef::create(Builder, visit(M->getInstanceType()), /*WasAbstract=*/true); @@ -1641,6 +1677,27 @@ class TypeRefSubstitution constraints); } + const TypeRef *visitSymbolicExtendedExistentialTypeRef( + const SymbolicExtendedExistentialTypeRef *SEET) { + std::vector reqs; + for (auto &req : SEET->getRequirements()) { + auto substReq = visitTypeRefRequirement(req); + if (!substReq) + continue; + reqs.emplace_back(*substReq); + } + + std::vector args; + for (auto *arg : SEET->getArguments()) { + auto *substArg = visit(arg); + if (!substArg) + return nullptr; + args.push_back(substArg); + } + return SymbolicExtendedExistentialTypeRef::create( + Builder, SEET->getProtocol(), reqs, args, SEET->getFlags()); + } + const TypeRef * visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) { auto found = Substitutions.find({GTP->getDepth(), GTP->getIndex()});