Skip to content

Commit d4cd0da

Browse files
committed
Reflection: Update for subclass existentials and primitive AnyObject
1 parent d13b431 commit d4cd0da

File tree

10 files changed

+382
-56
lines changed

10 files changed

+382
-56
lines changed

include/swift/Reflection/TypeRef.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -421,28 +421,39 @@ class ProtocolTypeRef final : public TypeRef {
421421
};
422422

423423
class ProtocolCompositionTypeRef final : public TypeRef {
424-
std::vector<const TypeRef *> Protocols;
424+
std::vector<const TypeRef *> Members;
425+
bool HasExplicitAnyObject;
425426

426-
static TypeRefID Profile(const std::vector<const TypeRef *> &Protocols) {
427+
static TypeRefID Profile(const std::vector<const TypeRef *> &Members,
428+
bool HasExplicitAnyObject) {
427429
TypeRefID ID;
428-
for (auto Protocol : Protocols) {
429-
ID.addPointer(Protocol);
430+
ID.addInteger((uint32_t)HasExplicitAnyObject);
431+
for (auto Member : Members) {
432+
ID.addPointer(Member);
430433
}
431434
return ID;
432435
}
433436

434437
public:
435-
ProtocolCompositionTypeRef(std::vector<const TypeRef *> Protocols)
436-
: TypeRef(TypeRefKind::ProtocolComposition), Protocols(Protocols) {}
438+
ProtocolCompositionTypeRef(std::vector<const TypeRef *> Members,
439+
bool HasExplicitAnyObject)
440+
: TypeRef(TypeRefKind::ProtocolComposition),
441+
Members(Members), HasExplicitAnyObject(HasExplicitAnyObject) {}
437442

438443
template <typename Allocator>
439444
static const ProtocolCompositionTypeRef *
440-
create(Allocator &A, std::vector<const TypeRef *> Protocols) {
441-
FIND_OR_CREATE_TYPEREF(A, ProtocolCompositionTypeRef, Protocols);\
445+
create(Allocator &A, std::vector<const TypeRef *> Members,
446+
bool HasExplicitAnyObject) {
447+
FIND_OR_CREATE_TYPEREF(A, ProtocolCompositionTypeRef, Members,
448+
HasExplicitAnyObject);
442449
}
443450

444-
const std::vector<const TypeRef *> &getProtocols() const {
445-
return Protocols;
451+
const std::vector<const TypeRef *> &getMembers() const {
452+
return Members;
453+
}
454+
455+
bool hasExplicitAnyObject() const {
456+
return HasExplicitAnyObject;
446457
}
447458

448459
static bool classof(const TypeRef *TR) {

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,16 @@ class TypeRefBuilder {
215215
}
216216

217217
const ProtocolCompositionTypeRef *
218-
createProtocolCompositionType(const std::vector<const TypeRef*> &protocols) {
219-
for (auto protocol : protocols) {
220-
if (!isa<ProtocolTypeRef>(protocol))
218+
createProtocolCompositionType(const std::vector<const TypeRef*> &members,
219+
bool hasExplicitAnyObject) {
220+
for (auto member : members) {
221+
if (!isa<ProtocolTypeRef>(member) &&
222+
!isa<NominalTypeRef>(member) &&
223+
!isa<BoundGenericTypeRef>(member))
221224
return nullptr;
222225
}
223-
return ProtocolCompositionTypeRef::create(*this, protocols);
226+
return ProtocolCompositionTypeRef::create(*this, members,
227+
hasExplicitAnyObject);
224228
}
225229

226230
const ExistentialMetatypeTypeRef *

include/swift/Remote/MetadataReader.h

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,42 @@ class TypeDecoder {
133133
}
134134
if (protocols.size() == 1)
135135
return protocols.front();
136-
else
137-
return Builder.createProtocolCompositionType(protocols);
136+
return Builder.createProtocolCompositionType(
137+
protocols,
138+
/*hasExplicitAnyObject=*/false);
139+
}
140+
case NodeKind::ProtocolListWithAnyObject: {
141+
std::vector<BuiltType> protocols;
142+
auto ProtocolList = Node->getChild(0);
143+
auto TypeList = ProtocolList->getChild(0);
144+
for (auto componentType : *TypeList) {
145+
if (auto protocol = decodeMangledType(componentType))
146+
protocols.push_back(protocol);
147+
else
148+
return BuiltType();
149+
}
150+
return Builder.createProtocolCompositionType(
151+
protocols,
152+
/*hasExplicitAnyObject=*/true);
153+
}
154+
case NodeKind::ProtocolListWithClass: {
155+
std::vector<BuiltType> members;
156+
auto ProtocolList = Node->getChild(0);
157+
auto TypeList = ProtocolList->getChild(0);
158+
for (auto componentType : *TypeList) {
159+
if (auto protocol = decodeMangledType(componentType))
160+
members.push_back(protocol);
161+
else
162+
return BuiltType();
163+
}
164+
165+
auto SuperclassNode = Node->getChild(1);
166+
if (auto superclass = decodeMangledType(SuperclassNode))
167+
members.push_back(superclass);
168+
169+
return Builder.createProtocolCompositionType(
170+
members,
171+
/*hasExplicitAnyObject=*/true);
138172
}
139173
case NodeKind::Protocol: {
140174
auto moduleName = Node->getChild(0)->getText();
@@ -724,7 +758,20 @@ class MetadataReader {
724758
}
725759
case MetadataKind::Existential: {
726760
auto Exist = cast<TargetExistentialTypeMetadata<Runtime>>(Meta);
727-
std::vector<BuiltType> Protocols;
761+
std::vector<BuiltType> Members;
762+
bool HasExplicitAnyObject = false;
763+
764+
if (Exist->Flags.hasSuperclassConstraint()) {
765+
// The superclass is stored after the list of protocols.
766+
auto SuperclassType = readTypeFromMetadata(
767+
Exist->Protocols[Exist->Protocols.NumProtocols]);
768+
if (!SuperclassType) return BuiltType();
769+
Members.push_back(SuperclassType);
770+
}
771+
772+
if (Exist->isClassBounded())
773+
HasExplicitAnyObject = true;
774+
728775
for (size_t i = 0; i < Exist->Protocols.NumProtocols; ++i) {
729776
auto ProtocolAddress = Exist->Protocols[i];
730777
auto ProtocolDescriptor = readProtocolDescriptor(ProtocolAddress);
@@ -741,9 +788,10 @@ class MetadataReader {
741788
if (!Protocol)
742789
return BuiltType();
743790

744-
Protocols.push_back(Protocol);
791+
Members.push_back(Protocol);
745792
}
746-
auto BuiltExist = Builder.createProtocolCompositionType(Protocols);
793+
auto BuiltExist = Builder.createProtocolCompositionType(
794+
Members, HasExplicitAnyObject);
747795
TypeCache[MetadataAddress] = BuiltExist;
748796
return BuiltExist;
749797
}
@@ -1061,6 +1109,14 @@ class MetadataReader {
10611109
case MetadataKind::ErrorObject:
10621110
return _readMetadata<TargetEnumMetadata>(address);
10631111
case MetadataKind::Existential: {
1112+
StoredPointer flagsAddress = address +
1113+
sizeof(StoredPointer);
1114+
1115+
StoredPointer flags;
1116+
if (!Reader->readInteger(RemoteAddress(flagsAddress),
1117+
&flags))
1118+
return nullptr;
1119+
10641120
StoredPointer numProtocolsAddress = address +
10651121
TargetExistentialTypeMetadata<Runtime>::OffsetToNumProtocols;
10661122
StoredPointer numProtocols;
@@ -1076,6 +1132,9 @@ class MetadataReader {
10761132
+ numProtocols *
10771133
sizeof(ConstTargetMetadataPointer<Runtime, TargetProtocolDescriptor>);
10781134

1135+
if (ExistentialTypeFlags(flags).hasSuperclassConstraint())
1136+
totalSize += sizeof(StoredPointer);
1137+
10791138
return _readMetadata(address, totalSize);
10801139
}
10811140
case MetadataKind::ExistentialMetatype:

lib/RemoteAST/RemoteAST.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,14 +318,15 @@ class RemoteASTTypeBuilder {
318318
return decl->getDeclaredType();
319319
}
320320

321-
Type createProtocolCompositionType(ArrayRef<Type> protocols) {
322-
for (auto protocol : protocols) {
323-
if (!protocol->is<ProtocolType>())
321+
Type createProtocolCompositionType(ArrayRef<Type> members,
322+
bool hasExplicitAnyObject) {
323+
for (auto member : members) {
324+
if (!member->isExistentialType() &&
325+
!member->getClassOrBoundGenericClass())
324326
return Type();
325327
}
326-
return ProtocolCompositionType::get(Ctx, protocols,
327-
// FIXME
328-
/*HasExplicitAnyObject=*/false);
328+
329+
return ProtocolCompositionType::get(Ctx, members, hasExplicitAnyObject);
329330
}
330331

331332
Type createExistentialMetatypeType(Type instance) {

stdlib/public/Reflection/TypeLowering.cpp

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,19 @@ BuiltinTypeInfo::BuiltinTypeInfo(const BuiltinTypeDescriptor *descriptor)
206206
/// Utility class for building values that contain witness tables.
207207
class ExistentialTypeInfoBuilder {
208208
TypeConverter &TC;
209-
ExistentialTypeRepresentation Representation;
210209
std::vector<const ProtocolTypeRef *> Protocols;
210+
ExistentialTypeRepresentation Representation;
211+
ReferenceCounting Refcounting;
211212
bool ObjC;
212213
unsigned WitnessTableCount;
213214
bool Invalid;
214215

215216
bool isSingleError() const {
217+
// If we changed representation, it means we added a
218+
// superclass constraint or an AnyObject member.
219+
if (Representation != ExistentialTypeRepresentation::Opaque)
220+
return false;
221+
216222
if (Protocols.size() != 1)
217223
return false;
218224

@@ -231,13 +237,6 @@ class ExistentialTypeInfoBuilder {
231237
}
232238

233239
for (auto *P : Protocols) {
234-
// FIXME: AnyObject should go away
235-
if (P->isAnyObject()) {
236-
Representation = ExistentialTypeRepresentation::Class;
237-
// No extra witness table for AnyObject
238-
continue;
239-
}
240-
241240
const FieldDescriptor *FD = TC.getBuilder().getFieldTypeInfo(P);
242241
if (FD == nullptr) {
243242
DEBUG(std::cerr << "No field descriptor: "; P->dump())
@@ -271,15 +270,76 @@ class ExistentialTypeInfoBuilder {
271270
public:
272271
ExistentialTypeInfoBuilder(TypeConverter &TC)
273272
: TC(TC), Representation(ExistentialTypeRepresentation::Opaque),
274-
ObjC(false), WitnessTableCount(0), Invalid(false) {}
273+
Refcounting(ReferenceCounting::Unknown),
274+
ObjC(false), WitnessTableCount(0),
275+
Invalid(false) {}
276+
277+
void addProtocol(const ProtocolTypeRef *P) {
278+
// FIXME: AnyObject should go away
279+
if (P->isAnyObject()) {
280+
Representation = ExistentialTypeRepresentation::Class;
281+
// No extra witness table for AnyObject
282+
return;
283+
}
275284

276-
void addProtocol(const TypeRef *TR) {
277-
if (auto *P = dyn_cast<const ProtocolTypeRef>(TR)) {
278-
Protocols.push_back(P);
279-
} else {
280-
DEBUG(std::cerr << "Not a protocol: "; TR->dump())
281-
Invalid = true;
285+
Protocols.push_back(P);
286+
}
287+
288+
void addProtocolComposition(const ProtocolCompositionTypeRef *PC) {
289+
for (auto *T : PC->getMembers()) {
290+
if (auto *P = dyn_cast<ProtocolTypeRef>(T)) {
291+
addProtocol(P);
292+
continue;
293+
}
294+
295+
if (auto *PC = dyn_cast<ProtocolCompositionTypeRef>(T)) {
296+
addProtocolComposition(PC);
297+
continue;
298+
}
299+
300+
// Anything else should either be a superclass constraint, or
301+
// we have an invalid typeref.
302+
if (!isa<NominalTypeRef>(T) &&
303+
!isa<BoundGenericTypeRef>(T)) {
304+
DEBUG(std::cerr << "Bad existential member: "; T->dump())
305+
Invalid = true;
306+
continue;
307+
}
308+
auto *FD = TC.getBuilder().getFieldTypeInfo(T);
309+
if (FD == nullptr) {
310+
DEBUG(std::cerr << "No field descriptor: "; T->dump())
311+
Invalid = true;
312+
continue;
313+
}
314+
315+
// We have a valid superclass constraint. It only affects
316+
// lowering by class-constraining the entire existential.
317+
switch (FD->Kind) {
318+
case FieldDescriptorKind::Class:
319+
Refcounting = ReferenceCounting::Native;
320+
LLVM_FALLTHROUGH;
321+
322+
case FieldDescriptorKind::ObjCClass:
323+
addAnyObject();
324+
break;
325+
326+
default:
327+
DEBUG(std::cerr << "Bad existential member: "; T->dump())
328+
Invalid = true;
329+
continue;
330+
}
282331
}
332+
333+
if (PC->hasExplicitAnyObject())
334+
addAnyObject();
335+
}
336+
337+
void addAnyObject() {
338+
Representation = ExistentialTypeRepresentation::Class;
339+
}
340+
341+
void markInvalid() {
342+
Invalid = true;
283343
}
284344

285345
const TypeInfo *build() {
@@ -295,7 +355,7 @@ class ExistentialTypeInfoBuilder {
295355
}
296356

297357
return TC.getReferenceTypeInfo(ReferenceKind::Strong,
298-
ReferenceCounting::Unknown);
358+
Refcounting);
299359
}
300360

301361
RecordKind Kind;
@@ -317,7 +377,10 @@ class ExistentialTypeInfoBuilder {
317377
case ExistentialTypeRepresentation::Class:
318378
// Class existentials consist of a single retainable pointer
319379
// followed by witness tables.
320-
builder.addField("object", TC.getUnknownObjectTypeRef());
380+
if (Refcounting == ReferenceCounting::Unknown)
381+
builder.addField("object", TC.getUnknownObjectTypeRef());
382+
else
383+
builder.addField("object", TC.getNativeObjectTypeRef());
321384
break;
322385
case ExistentialTypeRepresentation::Opaque: {
323386
auto *TI = TC.getTypeInfo(TC.getRawPointerTypeRef());
@@ -1097,8 +1160,7 @@ class LowerType
10971160
const TypeInfo *
10981161
visitProtocolCompositionTypeRef(const ProtocolCompositionTypeRef *PC) {
10991162
ExistentialTypeInfoBuilder builder(TC);
1100-
for (auto *P : PC->getProtocols())
1101-
builder.addProtocol(P);
1163+
builder.addProtocolComposition(PC);
11021164
return builder.build();
11031165
}
11041166

@@ -1124,8 +1186,7 @@ class LowerType
11241186
if (auto *P = dyn_cast<ProtocolTypeRef>(TR)) {
11251187
builder.addProtocol(P);
11261188
} else if (auto *PC = dyn_cast<ProtocolCompositionTypeRef>(TR)) {
1127-
for (auto *P : PC->getProtocols())
1128-
builder.addProtocol(P);
1189+
builder.addProtocolComposition(PC);
11291190
} else {
11301191
DEBUG(std::cerr << "Invalid existential metatype: "; EM->dump());
11311192
return nullptr;

stdlib/public/Reflection/TypeRef.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,10 @@ class PrintTypeRef : public TypeRefVisitor<PrintTypeRef, void> {
140140

141141
void visitProtocolCompositionTypeRef(const ProtocolCompositionTypeRef *PC) {
142142
printHeader("protocol_composition");
143-
for (auto protocol : PC->getProtocols())
144-
printRec(protocol);
143+
if (PC->hasExplicitAnyObject())
144+
OS << " any_object";
145+
for (auto member : PC->getMembers())
146+
printRec(member);
145147
OS << ')';
146148
}
147149

@@ -266,8 +268,8 @@ struct TypeRefIsConcrete
266268

267269
bool
268270
visitProtocolCompositionTypeRef(const ProtocolCompositionTypeRef *PC) {
269-
for (auto Protocol : PC->getProtocols())
270-
if (!visit(Protocol))
271+
for (auto Member : PC->getMembers())
272+
if (!visit(Member))
271273
return false;
272274
return true;
273275
}

test/Reflection/Inputs/TypeLowering.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ public struct ExistentialStruct {
113113

114114
public weak var weakAnyObject: AnyObject?
115115
public weak var weakAnyClassBoundProto: CP1?
116+
117+
public let classConstrainedP1: C & P1
116118
}
117119

118120
public struct MetadataHolder<T, U> {

0 commit comments

Comments
 (0)