Skip to content

Commit 420c6d1

Browse files
authored
Merge pull request #31026 from jckarter/opaque-type-reflection
`swift-reflection-dump` support for unresolved opaque return types.
2 parents 7e5a4f2 + 054bb2c commit 420c6d1

File tree

7 files changed

+186
-5
lines changed

7 files changed

+186
-5
lines changed

include/swift/Reflection/TypeRef.h

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ class TupleTypeRef final : public TypeRef {
316316

317317
public:
318318
TupleTypeRef(std::vector<const TypeRef *> Elements, bool Variadic=false)
319-
: TypeRef(TypeRefKind::Tuple), Elements(Elements), Variadic(Variadic) {}
319+
: TypeRef(TypeRefKind::Tuple), Elements(std::move(Elements)),
320+
Variadic(Variadic) {}
320321

321322
template <typename Allocator>
322323
static const TupleTypeRef *create(Allocator &A,
@@ -338,6 +339,84 @@ class TupleTypeRef final : public TypeRef {
338339
}
339340
};
340341

342+
class OpaqueArchetypeTypeRef final : public TypeRef {
343+
std::string ID;
344+
std::string Description;
345+
unsigned Ordinal;
346+
// Each ArrayRef in ArgumentLists references into the buffer owned by this
347+
// vector, which must not be modified after construction.
348+
std::vector<const TypeRef *> AllArgumentsBuf;
349+
std::vector<ArrayRef<const TypeRef *>> ArgumentLists;
350+
351+
static TypeRefID Profile(StringRef idString,
352+
StringRef description, unsigned ordinal,
353+
ArrayRef<ArrayRef<const TypeRef *>> argumentLists) {
354+
TypeRefID ID;
355+
ID.addString(idString);
356+
ID.addInteger(ordinal);
357+
for (auto argList : argumentLists) {
358+
ID.addInteger(0u);
359+
for (auto arg : argList)
360+
ID.addPointer(arg);
361+
}
362+
363+
return ID;
364+
}
365+
366+
public:
367+
OpaqueArchetypeTypeRef(StringRef id,
368+
StringRef description, unsigned ordinal,
369+
ArrayRef<ArrayRef<const TypeRef *>> argumentLists)
370+
: TypeRef(TypeRefKind::OpaqueArchetype),
371+
ID(id), Description(description), Ordinal(ordinal)
372+
{
373+
std::vector<unsigned> argumentListLengths;
374+
375+
for (auto argList : argumentLists) {
376+
argumentListLengths.push_back(argList.size());
377+
AllArgumentsBuf.insert(AllArgumentsBuf.end(),
378+
argList.begin(), argList.end());
379+
}
380+
auto *data = AllArgumentsBuf.data();
381+
for (auto length : argumentListLengths) {
382+
ArgumentLists.push_back(ArrayRef<const TypeRef *>(data, length));
383+
data += length;
384+
}
385+
assert(data == AllArgumentsBuf.data() + AllArgumentsBuf.size());
386+
}
387+
388+
template <typename Allocator>
389+
static const OpaqueArchetypeTypeRef *create(Allocator &A,
390+
StringRef id, StringRef description,
391+
unsigned ordinal,
392+
ArrayRef<ArrayRef<const TypeRef *>> arguments) {
393+
FIND_OR_CREATE_TYPEREF(A, OpaqueArchetypeTypeRef,
394+
id, description, ordinal, arguments);
395+
}
396+
397+
ArrayRef<ArrayRef<const TypeRef *>> getArgumentLists() const {
398+
return ArgumentLists;
399+
}
400+
401+
unsigned getOrdinal() const {
402+
return Ordinal;
403+
}
404+
405+
/// A stable identifier for the opaque type.
406+
StringRef getID() const {
407+
return ID;
408+
}
409+
410+
/// A human-digestible, but not necessarily stable, description of the opaque type.
411+
StringRef getDescription() const {
412+
return Description;
413+
}
414+
415+
static bool classof(const TypeRef *T) {
416+
return T->getKind() == TypeRefKind::OpaqueArchetype;
417+
}
418+
};
419+
341420
class FunctionTypeRef final : public TypeRef {
342421
using Param = remote::FunctionParam<const TypeRef *>;
343422

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ class TypeRefBuilder {
372372
unsigned ordinal) {
373373
// TODO: Produce a type ref for the opaque type if the underlying type isn't
374374
// available.
375+
opaqueDescriptor->dump();
375376

376377
// Try to resolve to the underlying type, if we can.
377378
if (opaqueDescriptor->getKind() ==
@@ -392,7 +393,15 @@ class TypeRefBuilder {
392393

393394
return underlyingTy->subst(*this, subs);
394395
}
395-
return nullptr;
396+
397+
// Otherwise, build a type ref that represents the opaque type.
398+
return OpaqueArchetypeTypeRef::create(*this,
399+
mangleNode(opaqueDescriptor,
400+
SymbolicResolver(),
401+
Dem),
402+
nodeToString(opaqueDescriptor),
403+
ordinal,
404+
genericArgs);
396405
}
397406

398407
const TupleTypeRef *

include/swift/Reflection/TypeRefs.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ TYPEREF(ForeignClass, TypeRef)
3030
TYPEREF(ObjCClass, TypeRef)
3131
TYPEREF(ObjCProtocol, TypeRef)
3232
TYPEREF(Opaque, TypeRef)
33+
TYPEREF(OpaqueArchetype, TypeRef)
3334
#define REF_STORAGE(Name, ...) \
3435
TYPEREF(Name##Storage, TypeRef)
3536
#include "swift/AST/ReferenceStorage.def"

include/swift/Remote/MetadataReader.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,11 +1077,16 @@ class MetadataReader {
10771077
demangledSymbol = demangledSymbol->getChild(0);
10781078
assert(demangledSymbol->getKind() == Demangle::Node::Kind::Type);
10791079
break;
1080-
// We don't handle pointers to other symbols yet.
1081-
// TODO: Opaque type descriptors could be useful.
1080+
// Pointers to opaque type descriptors demangle to the name of the opaque
1081+
// type declaration.
1082+
case Demangle::Node::Kind::OpaqueTypeDescriptor:
1083+
demangledSymbol = demangledSymbol->getChild(0);
1084+
break;
1085+
// We don't handle pointers to other symbols yet.
10821086
default:
10831087
return nullptr;
10841088
}
1089+
10851090
return demangledSymbol;
10861091
}
10871092

lib/Demangling/Demangler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,8 +716,10 @@ NodePointer Demangler::demangleSymbolicReference(unsigned char rawKind,
716716
return nullptr;
717717

718718
// Types register as substitutions even when symbolically referenced.
719+
// OOPS: Except for opaque type references!
719720
if (kind == SymbolicReferenceKind::Context &&
720-
resolved->getKind() != Node::Kind::OpaqueTypeDescriptorSymbolicReference)
721+
resolved->getKind() != Node::Kind::OpaqueTypeDescriptorSymbolicReference &&
722+
resolved->getKind() != Node::Kind::OpaqueReturnTypeOf)
721723
addSubstitution(resolved);
722724
return resolved;
723725
}

stdlib/public/Reflection/TypeLowering.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,10 @@ class HasFixedSize
15841584
bool visitOpaqueTypeRef(const OpaqueTypeRef *O) {
15851585
return false;
15861586
}
1587+
1588+
bool visitOpaqueArchetypeTypeRef(const OpaqueArchetypeTypeRef *O) {
1589+
return false;
1590+
}
15871591
};
15881592

15891593
bool TypeConverter::hasFixedSize(const TypeRef *TR) {
@@ -1705,6 +1709,10 @@ class HasSingletonMetatype
17051709
MetatypeRepresentation visitOpaqueTypeRef(const OpaqueTypeRef *O) {
17061710
return MetatypeRepresentation::Unknown;
17071711
}
1712+
1713+
MetatypeRepresentation visitOpaqueArchetypeTypeRef(const OpaqueArchetypeTypeRef *O) {
1714+
return MetatypeRepresentation::Unknown;
1715+
}
17081716
};
17091717

17101718
class EnumTypeInfoBuilder {
@@ -2153,6 +2161,13 @@ class LowerType
21532161
DEBUG_LOG(fprintf(stderr, "Can't lower opaque TypeRef"));
21542162
return nullptr;
21552163
}
2164+
2165+
const TypeInfo *visitOpaqueArchetypeTypeRef(const OpaqueArchetypeTypeRef *O) {
2166+
// TODO: Provide a hook for the client to try to resolve the opaque archetype
2167+
// with additional information?
2168+
DEBUG_LOG(fprintf(stderr, "Can't lower unresolved opaque archetype TypeRef"));
2169+
return nullptr;
2170+
}
21562171
};
21572172

21582173
const TypeInfo *TypeConverter::getTypeInfo(const TypeRef *TR) {

stdlib/public/Reflection/TypeRef.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,22 @@ class PrintTypeRef : public TypeRefVisitor<PrintTypeRef, void> {
256256
fprintf(file, ")");
257257
}
258258

259+
void visitOpaqueArchetypeTypeRef(const OpaqueArchetypeTypeRef *O) {
260+
printHeader("opaque_archetype");
261+
printField("id", O->getID());
262+
printField("description", O->getDescription());
263+
fprintf(file, " ordinal %u ", O->getOrdinal());
264+
for (auto argList : O->getArgumentLists()) {
265+
fprintf(file, "\n");
266+
fprintf(indent(Indent + 2), "args: <");
267+
for (auto arg : argList) {
268+
printRec(arg);
269+
}
270+
fprintf(file, ">");
271+
}
272+
fprintf(file, ")");
273+
}
274+
259275
void visitOpaqueTypeRef(const OpaqueTypeRef *O) {
260276
printHeader("opaque");
261277
fprintf(file, ")");
@@ -348,6 +364,10 @@ struct TypeRefIsConcrete
348364
bool visitOpaqueTypeRef(const OpaqueTypeRef *O) {
349365
return true;
350366
}
367+
368+
bool visitOpaqueArchetypeTypeRef(const OpaqueArchetypeTypeRef *O) {
369+
return false;
370+
}
351371

352372
#define REF_STORAGE(Name, name, ...) \
353373
bool visit##Name##StorageTypeRef(const Name##StorageTypeRef *US) { \
@@ -660,6 +680,36 @@ class DemanglingForTypeRef
660680
Demangle::NodePointer visitOpaqueTypeRef(const OpaqueTypeRef *O) {
661681
return Dem.createNode(Node::Kind::OpaqueType);
662682
}
683+
684+
Demangle::NodePointer visitOpaqueArchetypeTypeRef(const OpaqueArchetypeTypeRef *O) {
685+
auto decl = Dem.demangleSymbol(O->getID());
686+
if (!decl)
687+
return nullptr;
688+
689+
auto index = Dem.createNode(Node::Kind::Index, O->getOrdinal());
690+
691+
auto argNodeLists = Dem.createNode(Node::Kind::TypeList);
692+
for (auto argList : O->getArgumentLists()) {
693+
auto argNodeList = Dem.createNode(Node::Kind::TypeList);
694+
695+
for (auto arg : argList) {
696+
auto argNode = visit(arg);
697+
if (!argNode)
698+
return nullptr;
699+
700+
argNodeList->addChild(argNode, Dem);
701+
}
702+
703+
argNodeLists->addChild(argNodeList, Dem);
704+
}
705+
706+
auto node = Dem.createNode(Node::Kind::OpaqueType);
707+
node->addChild(decl, Dem);
708+
node->addChild(index, Dem);
709+
node->addChild(argNodeLists, Dem);
710+
711+
return node;
712+
}
663713
};
664714

665715
Demangle::NodePointer TypeRef::getDemangling(Demangle::Demangler &Dem) const {
@@ -831,6 +881,11 @@ class ThickenMetatype
831881
const TypeRef *visitOpaqueTypeRef(const OpaqueTypeRef *O) {
832882
return O;
833883
}
884+
885+
const TypeRef *visitOpaqueArchetypeTypeRef(const OpaqueArchetypeTypeRef *O) {
886+
return O;
887+
}
888+
834889
};
835890

836891
static const TypeRef *
@@ -1009,6 +1064,21 @@ class TypeRefSubstitution
10091064
const TypeRef *visitOpaqueTypeRef(const OpaqueTypeRef *O) {
10101065
return O;
10111066
}
1067+
1068+
const TypeRef *visitOpaqueArchetypeTypeRef(const OpaqueArchetypeTypeRef *O) {
1069+
std::vector<const TypeRef *> newArgsBuffer;
1070+
for (auto argList : O->getArgumentLists()) {
1071+
for (auto arg : argList) {
1072+
newArgsBuffer.push_back(visit(arg));
1073+
}
1074+
}
1075+
1076+
std::vector<ArrayRef<const TypeRef *>> newArgLists;
1077+
1078+
return OpaqueArchetypeTypeRef::create(Builder, O->getID(), O->getDescription(),
1079+
O->getOrdinal(),
1080+
newArgLists);
1081+
}
10121082
};
10131083

10141084
const TypeRef *

0 commit comments

Comments
 (0)