Skip to content

Commit cc611de

Browse files
authored
Merge pull request #8788 from slavapestov/subclass-existentials-irgen
Tiny bit more progress on IRGen support for subclass existentials
2 parents 767e8f3 + 03373a1 commit cc611de

19 files changed

+309
-169
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,10 @@ ERROR(sil_member_decl_type_mismatch,none,
528528
"member defined with mismatching type %0 (expected %1)", (Type, Type))
529529
ERROR(sil_substitution_mismatch,none,
530530
"substitution replacement type %0 does not conform to protocol %1",
531-
(Type, DeclName))
531+
(Type, Type))
532+
ERROR(sil_not_class,none,
533+
"substitution replacement type %0 is not a class type",
534+
(Type))
532535
ERROR(sil_missing_substitutions,none,
533536
"missing substitutions", ())
534537
ERROR(sil_too_many_substitutions,none,

include/swift/AST/Type.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,6 @@ class CanType : public Type {
351351
static bool isReferenceTypeImpl(CanType type, bool functionsCount);
352352
static bool isExistentialTypeImpl(CanType type);
353353
static bool isAnyExistentialTypeImpl(CanType type);
354-
static void getExistentialTypeProtocolsImpl(CanType type,
355-
SmallVectorImpl<ProtocolDecl*> &protocols);
356354
static bool isObjCExistentialTypeImpl(CanType type);
357355
static CanType getAnyOptionalObjectTypeImpl(CanType type,
358356
OptionalTypeKind &kind);
@@ -406,11 +404,6 @@ class CanType : public Type {
406404
return isAnyExistentialTypeImpl(*this);
407405
}
408406

409-
/// Given that this type is an existential, return its
410-
/// protocols in a canonical order.
411-
void getExistentialTypeProtocols(
412-
SmallVectorImpl<ProtocolDecl *> &protocols);
413-
414407
/// Break an existential down into a set of constraints.
415408
ExistentialLayout getExistentialLayout();
416409

include/swift/AST/Types.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,10 +586,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
586586
/// bound.
587587
bool isClassExistentialType();
588588

589-
/// Given that this type is an existential type, produce
590-
/// its list of protocols.
591-
void getExistentialTypeProtocols(SmallVectorImpl<ProtocolDecl *> &protocols);
592-
593589
/// Break an existential down into a set of constraints.
594590
ExistentialLayout getExistentialLayout();
595591

lib/AST/ASTVerifier.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,11 +1128,10 @@ class Verifier : public ASTWalker {
11281128
abort();
11291129
}
11301130

1131-
SmallVector<ProtocolDecl*, 1> protocols;
1132-
srcTy->getExistentialTypeProtocols(protocols);
1133-
1134-
if (protocols.size() != 1
1135-
|| !protocols[0]->isObjC()) {
1131+
auto layout = srcTy->getExistentialLayout();
1132+
if (layout.superclass ||
1133+
!layout.isObjC() ||
1134+
layout.getProtocols().size() != 1) {
11361135
Out << "ProtocolMetatypeToObject with non-ObjC-protocol metatype:\n";
11371136
E->print(Out);
11381137
Out << "\n";

lib/AST/Type.cpp

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -208,22 +208,6 @@ bool TypeBase::allowsOwnership() {
208208
return getCanonicalType().isAnyClassReferenceType();
209209
}
210210

211-
void TypeBase::getExistentialTypeProtocols(
212-
SmallVectorImpl<ProtocolDecl*> &protocols) {
213-
getCanonicalType().getExistentialTypeProtocols(protocols);
214-
}
215-
216-
void CanType::getExistentialTypeProtocols(
217-
SmallVectorImpl<ProtocolDecl*> &protocols) {
218-
// FIXME: Remove this completely
219-
auto layout = getExistentialLayout();
220-
assert(!layout.superclass && "Subclass existentials not fully supported yet");
221-
assert((!layout.requiresClass || layout.requiresClassImplied) &&
222-
"Explicit AnyObject should not appear yet");
223-
for (auto proto : layout.getProtocols())
224-
protocols.push_back(proto->getDecl());
225-
}
226-
227211
ExistentialLayout::ExistentialLayout(ProtocolType *type) {
228212
assert(type->isCanonical());
229213

@@ -2637,7 +2621,7 @@ void ArchetypeType::populateNestedTypes() const {
26372621
ProtocolType::visitAllProtocols(getConformsTo(),
26382622
[&](ProtocolDecl *proto) -> bool {
26392623
// Objective-C protocols don't have type members.
2640-
if (proto->hasClangNode()) return false;
2624+
if (proto->isObjC()) return false;
26412625

26422626
for (auto member : proto->getMembers()) {
26432627
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
@@ -3977,7 +3961,6 @@ static bool doesOpaqueClassUseNativeReferenceCounting(const ASTContext &ctx) {
39773961

39783962
static bool usesNativeReferenceCounting(ClassDecl *theClass,
39793963
ResilienceExpansion resilience) {
3980-
// NOTE: if you change this, change irgen::getReferenceCountingForClass.
39813964
// TODO: Resilience? there might be some legal avenue of changing this.
39823965
while (Type supertype = theClass->getSuperclass()) {
39833966
theClass = supertype->getClassOrBoundGenericClass();
@@ -3987,8 +3970,6 @@ static bool usesNativeReferenceCounting(ClassDecl *theClass,
39873970
}
39883971

39893972
bool TypeBase::usesNativeReferenceCounting(ResilienceExpansion resilience) {
3990-
assert(allowsOwnership());
3991-
39923973
CanType type = getCanonicalType();
39933974
switch (type->getKind()) {
39943975
#define SUGARED_TYPE(id, parent) case TypeKind::id:
@@ -4011,24 +3992,34 @@ bool TypeBase::usesNativeReferenceCounting(ResilienceExpansion resilience) {
40113992
return ::usesNativeReferenceCounting(
40123993
cast<BoundGenericClassType>(type)->getDecl(),
40133994
resilience);
3995+
case TypeKind::UnboundGeneric:
3996+
return ::usesNativeReferenceCounting(
3997+
cast<ClassDecl>(cast<UnboundGenericType>(type)->getDecl()),
3998+
resilience);
40143999

40154000
case TypeKind::DynamicSelf:
40164001
return cast<DynamicSelfType>(type).getSelfType()
40174002
->usesNativeReferenceCounting(resilience);
40184003

40194004
case TypeKind::Archetype: {
40204005
auto archetype = cast<ArchetypeType>(type);
4021-
assert(archetype->requiresClass());
4006+
auto layout = archetype->getLayoutConstraint();
4007+
assert(archetype->requiresClass() ||
4008+
(layout && layout->isRefCounted()));
40224009
if (auto supertype = archetype->getSuperclass())
40234010
return supertype->usesNativeReferenceCounting(resilience);
40244011
return ::doesOpaqueClassUseNativeReferenceCounting(type->getASTContext());
40254012
}
40264013

40274014
case TypeKind::Protocol:
4028-
case TypeKind::ProtocolComposition:
4015+
case TypeKind::ProtocolComposition: {
4016+
auto layout = getExistentialLayout();
4017+
assert(layout.requiresClass && "Opaque existentials don't use refcounting");
4018+
if (layout.superclass)
4019+
return layout.superclass->usesNativeReferenceCounting(resilience);
40294020
return ::doesOpaqueClassUseNativeReferenceCounting(type->getASTContext());
4021+
}
40304022

4031-
case TypeKind::UnboundGeneric:
40324023
case TypeKind::Function:
40334024
case TypeKind::GenericFunction:
40344025
case TypeKind::SILFunction:

lib/ClangImporter/ImportDecl.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/Builtins.h"
2424
#include "swift/AST/Decl.h"
2525
#include "swift/AST/DiagnosticsClangImporter.h"
26+
#include "swift/AST/ExistentialLayout.h"
2627
#include "swift/AST/Expr.h"
2728
#include "swift/AST/GenericEnvironment.h"
2829
#include "swift/AST/GenericSignature.h"
@@ -4742,12 +4743,15 @@ static bool inheritanceListContainsProtocol(ArrayRef<TypeLoc> inherited,
47424743
return llvm::any_of(inherited, [proto](TypeLoc type) -> bool {
47434744
if (!type.getType()->isExistentialType())
47444745
return false;
4745-
SmallVector<ProtocolDecl *, 8> protos;
4746-
type.getType()->getExistentialTypeProtocols(protos);
4747-
return ProtocolType::visitAllProtocols(protos,
4748-
[proto](const ProtocolDecl *next) {
4749-
return next == proto;
4750-
});
4746+
4747+
auto layout = type.getType()->getExistentialLayout();
4748+
for (auto protoTy : layout.getProtocols()) {
4749+
auto *protoDecl = protoTy->getDecl();
4750+
if (protoDecl == proto || protoDecl->inheritsFrom(proto))
4751+
return true;
4752+
}
4753+
4754+
return false;
47514755
});
47524756
}
47534757

lib/FrontendTool/ReferenceDependencies.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/AST/Decl.h"
1717
#include "swift/AST/DiagnosticEngine.h"
1818
#include "swift/AST/DiagnosticsFrontend.h"
19+
#include "swift/AST/ExistentialLayout.h"
1920
#include "swift/AST/Module.h"
2021
#include "swift/AST/ModuleLoader.h"
2122
#include "swift/AST/NameLookup.h"
@@ -85,18 +86,24 @@ static bool declIsPrivate(const Decl *member) {
8586
}
8687

8788
static bool extendedTypeIsPrivate(TypeLoc inheritedType) {
88-
if (!inheritedType.getType())
89+
auto type = inheritedType.getType();
90+
if (!type)
8991
return true;
9092

91-
if (!inheritedType.getType()->isExistentialType()) {
93+
if (!type->isExistentialType()) {
9294
// Be conservative. We don't know how to deal with other extended types.
9395
return false;
9496
}
9597

96-
SmallVector<ProtocolDecl *, 2> protocols;
97-
inheritedType.getType()->getExistentialTypeProtocols(protocols);
98+
auto layout = type->getExistentialLayout();
99+
assert(!layout.superclass && "Should not have a subclass existential "
100+
"in the inheritance clause of an extension");
101+
for (auto protoTy : layout.getProtocols()) {
102+
if (!declIsPrivate(protoTy->getDecl()))
103+
return false;
104+
}
98105

99-
return std::all_of(protocols.begin(), protocols.end(), declIsPrivate);
106+
return true;
100107
}
101108

102109
static std::string mangleTypeAsContext(const NominalTypeDecl *type) {
@@ -172,6 +179,8 @@ bool swift::emitReferenceDependencies(DiagnosticEngine &diags,
172179
break;
173180
}
174181

182+
// Check if the extension is just adding members, or if it is
183+
// introducing a conformance to a public protocol.
175184
bool justMembers = std::all_of(ED->getInherited().begin(),
176185
ED->getInherited().end(),
177186
extendedTypeIsPrivate);

lib/IRGen/GenArchetype.cpp

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -277,32 +277,28 @@ llvm::Value *irgen::emitAssociatedTypeMetadataRef(IRGenFunction &IGF,
277277
const TypeInfo *TypeConverter::convertArchetypeType(ArchetypeType *archetype) {
278278
assert(isExemplarArchetype(archetype) && "lowering non-exemplary archetype");
279279

280-
LayoutConstraint LayoutInfo = archetype->getLayoutConstraint();
280+
auto layout = archetype->getLayoutConstraint();
281281

282282
// If the archetype is class-constrained, use a class pointer
283283
// representation.
284284
if (archetype->requiresClass() ||
285-
(LayoutInfo && LayoutInfo->isRefCounted())) {
286-
ReferenceCounting refcount;
287-
llvm::PointerType *reprTy;
285+
(layout && layout->isRefCounted())) {
286+
auto refcount = getReferenceCountingForType(IGM, CanType(archetype));
288287

289-
if (!IGM.ObjCInterop) {
290-
refcount = ReferenceCounting::Native;
291-
reprTy = IGM.RefCountedPtrTy;
292-
} else {
293-
refcount = ReferenceCounting::Unknown;
294-
reprTy = IGM.UnknownRefCountedPtrTy;
295-
}
288+
llvm::PointerType *reprTy;
296289

297290
// If the archetype has a superclass constraint, it has at least the
298291
// retain semantics of its superclass, and it can be represented with
299292
// the supertype's pointer type.
300-
if (Type super = archetype->getSuperclass()) {
301-
ClassDecl *superClass = super->getClassOrBoundGenericClass();
302-
refcount = getReferenceCountingForClass(IGM, superClass);
303-
293+
if (auto super = archetype->getSuperclass()) {
304294
auto &superTI = IGM.getTypeInfoForUnlowered(super);
305295
reprTy = cast<llvm::PointerType>(superTI.StorageType);
296+
} else {
297+
if (refcount == ReferenceCounting::Native) {
298+
reprTy = IGM.RefCountedPtrTy;
299+
} else {
300+
reprTy = IGM.UnknownRefCountedPtrTy;
301+
}
306302
}
307303

308304
// As a hack, assume class archetypes never have spare bits. There's a
@@ -320,9 +316,9 @@ const TypeInfo *TypeConverter::convertArchetypeType(ArchetypeType *archetype) {
320316

321317
// If the archetype is trivial fixed-size layout-constrained, use a fixed size
322318
// representation.
323-
if (LayoutInfo && LayoutInfo->isFixedSizeTrivial()) {
324-
Size size(LayoutInfo->getTrivialSizeInBytes());
325-
Alignment align(LayoutInfo->getTrivialSizeInBytes());
319+
if (layout && layout->isFixedSizeTrivial()) {
320+
Size size(layout->getTrivialSizeInBytes());
321+
Alignment align(layout->getTrivialSizeInBytes());
326322
auto spareBits =
327323
SpareBitVector::getConstant(size.getValueInBits(), false);
328324
// Get an integer type of the required size.
@@ -336,7 +332,7 @@ const TypeInfo *TypeConverter::convertArchetypeType(ArchetypeType *archetype) {
336332
// If the archetype is a trivial layout-constrained, use a POD
337333
// representation. This type is not loadable, but it is known
338334
// to be a POD.
339-
if (LayoutInfo && LayoutInfo->isAddressOnlyTrivial()) {
335+
if (layout && layout->isAddressOnlyTrivial()) {
340336
// TODO: Create NonFixedSizeArchetypeTypeInfo and return it.
341337
}
342338

lib/IRGen/GenClass.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,25 @@ static ClassDecl *getRootClass(ClassDecl *theClass) {
6363
return theClass;
6464
}
6565

66-
/// What reference counting mechanism does a class have?
67-
ReferenceCounting irgen::getReferenceCountingForClass(IRGenModule &IGM,
68-
ClassDecl *theClass) {
66+
/// What reference counting mechanism does a class-like type have?
67+
ReferenceCounting irgen::getReferenceCountingForType(IRGenModule &IGM,
68+
CanType type) {
6969
// If ObjC interop is disabled, we have a Swift refcount.
7070
if (!IGM.ObjCInterop)
7171
return ReferenceCounting::Native;
7272

73-
// NOTE: if you change this, change Type::usesNativeReferenceCounting.
74-
// If the root class is implemented in swift, then we have a swift
75-
// refcount; otherwise, we have an ObjC refcount.
76-
if (getRootClass(theClass)->hasKnownSwiftImplementation())
73+
if (type->usesNativeReferenceCounting(ResilienceExpansion::Maximal))
7774
return ReferenceCounting::Native;
7875

79-
return ReferenceCounting::ObjC;
76+
// Class-constrained archetypes and existentials that don't use
77+
// native reference counting and yet have a superclass must be
78+
// using ObjC reference counting.
79+
auto superclass = type->getSuperclass(nullptr);
80+
if (superclass)
81+
return ReferenceCounting::ObjC;
82+
83+
// Otherwise, it could be either one.
84+
return ReferenceCounting::Unknown;
8085
}
8186

8287
/// What isa encoding mechanism does a type have?
@@ -2087,7 +2092,7 @@ const TypeInfo *
20872092
TypeConverter::convertClassType(CanType type, ClassDecl *D) {
20882093
llvm::StructType *ST = IGM.createNominalType(type);
20892094
llvm::PointerType *irType = ST->getPointerTo();
2090-
ReferenceCounting refcount = ::getReferenceCountingForClass(IGM, D);
2095+
ReferenceCounting refcount = ::getReferenceCountingForType(IGM, type);
20912096

20922097
SpareBitVector spareBits;
20932098

lib/IRGen/GenClass.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ namespace irgen {
132132
/// correspond to the runtime alignment of instances of the class.
133133
llvm::Constant *tryEmitClassConstantFragileInstanceAlignMask(IRGenModule &IGM,
134134
ClassDecl *theClass);
135-
136-
/// What reference counting mechanism does a class use?
137-
ReferenceCounting getReferenceCountingForClass(IRGenModule &IGM,
138-
ClassDecl *theClass);
139-
135+
136+
/// What reference counting mechanism does a class-like type use?
137+
ReferenceCounting getReferenceCountingForType(IRGenModule &IGM,
138+
CanType type);
139+
140140
/// What isa-encoding mechanism does a type use?
141141
IsaEncoding getIsaEncodingForType(IRGenModule &IGM, CanType type);
142142

0 commit comments

Comments
 (0)