Skip to content

Commit fa9be32

Browse files
committed
[NFC] Collect protocol decls, not type, in ExistentialLayout
Another thing that will be necessary for correctness with compositions of parameterized protocols.
1 parent 3fa6286 commit fa9be32

27 files changed

+98
-118
lines changed

include/swift/AST/ExistentialLayout.h

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include "swift/Basic/ArrayRefView.h"
2121
#include "swift/AST/ASTContext.h"
22-
#include "swift/AST/Type.h"
22+
#include "swift/AST/Types.h"
2323

2424
namespace swift {
2525
class ProtocolDecl;
@@ -33,12 +33,11 @@ struct ExistentialLayout {
3333
hasExplicitAnyObject = false;
3434
containsNonObjCProtocol = false;
3535
containsParameterized = false;
36-
singleProtocol = nullptr;
3736
}
3837

39-
ExistentialLayout(ProtocolType *type);
40-
ExistentialLayout(ProtocolCompositionType *type);
41-
ExistentialLayout(ParameterizedProtocolType *type);
38+
ExistentialLayout(CanProtocolType type);
39+
ExistentialLayout(CanProtocolCompositionType type);
40+
ExistentialLayout(CanParameterizedProtocolType type);
4241

4342
/// The explicit superclass constraint, if any.
4443
Type explicitSuperclass;
@@ -91,28 +90,17 @@ struct ExistentialLayout {
9190
/// constraints?
9291
bool isErrorExistential() const;
9392

94-
static inline ProtocolType *getProtocolType(const Type &Ty) {
95-
return cast<ProtocolType>(Ty.getPointer());
96-
}
97-
typedef ArrayRefView<Type,ProtocolType*,getProtocolType> ProtocolTypeArrayRef;
98-
99-
ProtocolTypeArrayRef getProtocols() const & {
100-
if (singleProtocol)
101-
return llvm::makeArrayRef(&singleProtocol, 1);
93+
ArrayRef<ProtocolDecl*> getProtocols() const & {
10294
return protocols;
10395
}
104-
/// The returned ArrayRef may point directly to \c this->singleProtocol, so
96+
/// The returned ArrayRef points to internal storage, so
10597
/// calling this on a temporary is likely to be incorrect.
106-
ProtocolTypeArrayRef getProtocols() const && = delete;
98+
ArrayRef<ProtocolDecl*> getProtocols() const && = delete;
10799

108100
LayoutConstraint getLayoutConstraint() const;
109101

110102
private:
111-
// The protocol from a ProtocolType
112-
Type singleProtocol;
113-
114-
/// Zero or more protocol constraints from a ProtocolCompositionType
115-
ArrayRef<Type> protocols;
103+
SmallVector<ProtocolDecl *, 4> protocols;
116104

117105
/// Zero or more primary associated type requirements from a
118106
/// ParameterizedProtocolType

include/swift/AST/Types.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2768,6 +2768,7 @@ BEGIN_CAN_TYPE_WRAPPER(ExistentialMetatypeType, AnyMetatypeType)
27682768
MetatypeRepresentation repr) {
27692769
return CanExistentialMetatypeType(ExistentialMetatypeType::get(type, repr));
27702770
}
2771+
PROXY_CAN_TYPE_SIMPLE_GETTER(getExistentialInstanceType)
27712772
END_CAN_TYPE_WRAPPER(ExistentialMetatypeType, AnyMetatypeType)
27722773

27732774
/// ModuleType - This is the type given to a module value, e.g. the "Builtin" in
@@ -5254,6 +5255,9 @@ class ProtocolCompositionType final : public TypeBase,
52545255
}
52555256
};
52565257
BEGIN_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)
5258+
CanTypeArrayRef getMembers() const {
5259+
return CanTypeArrayRef(getPointer()->getMembers());
5260+
}
52575261
END_CAN_TYPE_WRAPPER(ProtocolCompositionType, Type)
52585262

52595263
/// ParameterizedProtocolType - A type that constrains one or more primary
@@ -5291,11 +5295,19 @@ class ParameterizedProtocolType final : public TypeBase,
52915295
return Base;
52925296
}
52935297

5298+
ProtocolDecl *getProtocol() const {
5299+
return Base->getDecl();
5300+
}
5301+
52945302
ArrayRef<Type> getArgs() const {
52955303
return {getTrailingObjects<Type>(),
52965304
Bits.ParameterizedProtocolType.ArgCount};
52975305
}
52985306

5307+
bool requiresClass() const {
5308+
return getBaseType()->requiresClass();
5309+
}
5310+
52995311
void getRequirements(Type baseType, SmallVectorImpl<Requirement> &reqs) const;
53005312

53015313
void Profile(llvm::FoldingSetNodeID &ID) {
@@ -5317,7 +5329,9 @@ class ParameterizedProtocolType final : public TypeBase,
53175329
RecursiveTypeProperties properties);
53185330
};
53195331
BEGIN_CAN_TYPE_WRAPPER(ParameterizedProtocolType, Type)
5320-
PROXY_CAN_TYPE_SIMPLE_GETTER(getBaseType)
5332+
CanProtocolType getBaseType() const {
5333+
return CanProtocolType(getPointer()->getBaseType());
5334+
}
53215335
CanTypeArrayRef getArgs() const {
53225336
return CanTypeArrayRef(getPointer()->getArgs());
53235337
}
@@ -5348,6 +5362,9 @@ class ExistentialType final : public TypeBase {
53485362
if (auto composition = ConstraintType->getAs<ProtocolCompositionType>())
53495363
return composition->requiresClass();
53505364

5365+
if (auto paramProtocol = ConstraintType->getAs<ParameterizedProtocolType>())
5366+
return paramProtocol->requiresClass();
5367+
53515368
return false;
53525369
}
53535370

lib/AST/ASTMangler.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,8 +1045,7 @@ void ASTMangler::appendExistentialLayout(
10451045
bool First = true;
10461046
bool DroppedRequiresClass = false;
10471047
bool SawRequiresClass = false;
1048-
for (Type protoTy : layout.getProtocols()) {
1049-
auto proto = protoTy->castTo<ProtocolType>()->getDecl();
1048+
for (auto proto : layout.getProtocols()) {
10501049
// If we aren't allowed to emit marker protocols, suppress them here.
10511050
if (!AllowMarkerProtocols && proto->isMarkerProtocol()) {
10521051
if (proto->requiresClass())
@@ -1058,7 +1057,7 @@ void ASTMangler::appendExistentialLayout(
10581057
if (proto->requiresClass())
10591058
SawRequiresClass = true;
10601059

1061-
appendProtocolName(protoTy->castTo<ProtocolType>()->getDecl());
1060+
appendProtocolName(proto);
10621061
appendListSeparator(First);
10631062
}
10641063
if (First)
@@ -1258,7 +1257,8 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
12581257

12591258
case TypeKind::Protocol: {
12601259
return appendExistentialLayout(
1261-
ExistentialLayout(cast<ProtocolType>(tybase)), sig, forDecl);
1260+
ExistentialLayout(CanProtocolType(cast<ProtocolType>(tybase))),
1261+
sig, forDecl);
12621262
}
12631263

12641264
case TypeKind::ProtocolComposition: {

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2768,8 +2768,8 @@ static bool usesFeatureRethrowsProtocol(
27682768
if (auto inheritedType = inheritedEntry.getType()) {
27692769
if (inheritedType->isExistentialType()) {
27702770
auto layout = inheritedType->getExistentialLayout();
2771-
for (ProtocolType *protoTy : layout.getProtocols()) {
2772-
if (usesFeatureRethrowsProtocol(protoTy->getDecl(), checked))
2771+
for (ProtocolDecl *proto : layout.getProtocols()) {
2772+
if (usesFeatureRethrowsProtocol(proto, checked))
27732773
return true;
27742774
}
27752775
}

lib/AST/ClangTypeConverter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,8 +728,8 @@ ClangTypeConverter::visitProtocolCompositionType(ProtocolCompositionType *type)
728728
clangTy->getAs<clang::ObjCObjectPointerType>()->getPointeeType());
729729
}
730730

731-
for (Type t : layout.getProtocols()) {
732-
auto clangTy = convert(t);
731+
for (ProtocolDecl *proto : layout.getProtocols()) {
732+
auto clangTy = convert(proto->getDeclaredInterfaceType());
733733
if (clangTy.isNull())
734734
return clang::QualType();
735735
for (auto p : clangTy->getAs<clang::ObjCObjectPointerType>()->quals())

lib/AST/GenericEnvironment.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,8 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
366366
if (depType->is<GenericTypeParamType>()) {
367367
auto layout = getOpenedExistentialType()->getExistentialLayout();
368368
SmallVector<ProtocolDecl *, 2> protos;
369-
for (auto protoType : layout.getProtocols())
370-
protos.push_back(protoType->getDecl());
369+
for (auto proto : layout.getProtocols())
370+
protos.push_back(proto);
371371

372372
result = OpenedArchetypeType::getNew(this, requirements.anchor, protos,
373373
superclass, requirements.layout);

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4471,7 +4471,7 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
44714471
// getLookupConformanceFns used in here don't use that parameter anyway.
44724472
auto dependentType = CanType();
44734473
auto conformance =
4474-
getLookupConformanceFn()(dependentType, subjectType, proto->getDecl());
4474+
getLookupConformanceFn()(dependentType, subjectType, proto);
44754475

44764476
// FIXME: diagnose if there's no conformance.
44774477
if (conformance) {
@@ -4551,8 +4551,7 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
45514551
anyErrors = true;
45524552
}
45534553

4554-
for (auto *proto : layout.getProtocols()) {
4555-
auto *protoDecl = proto->getDecl();
4554+
for (auto *protoDecl : layout.getProtocols()) {
45564555
if (isErrorResult(addConformanceRequirement(resolvedSubject, protoDecl,
45574556
source)))
45584557
anyErrors = true;

lib/AST/Module.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,8 +1020,7 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
10201020
}
10211021

10221022
// Otherwise, the existential might conform abstractly.
1023-
for (auto proto : layout.getProtocols()) {
1024-
auto *protoDecl = proto->getDecl();
1023+
for (auto protoDecl : layout.getProtocols()) {
10251024

10261025
// If we found the protocol we're looking for, return an abstract
10271026
// conformance to it.

lib/AST/NameLookup.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,8 +1624,7 @@ void namelookup::extractDirectlyReferencedNominalTypes(
16241624
if (auto compositionTy = type->getAs<ProtocolCompositionType>()) {
16251625
auto layout = compositionTy->getExistentialLayout();
16261626

1627-
for (auto proto : layout.getProtocols()) {
1628-
auto *protoDecl = proto->getDecl();
1627+
for (auto protoDecl : layout.getProtocols()) {
16291628
decls.push_back(protoDecl);
16301629
}
16311630

@@ -2304,8 +2303,8 @@ static DirectlyReferencedTypeDecls directReferencesForType(Type type) {
23042303
}
23052304

23062305
// Protocols.
2307-
for (auto protocolTy : layout.getProtocols())
2308-
result.push_back(protocolTy->getDecl());
2306+
for (auto protoDecl : layout.getProtocols())
2307+
result.push_back(protoDecl);
23092308
return result;
23102309
}
23112310

lib/AST/Type.cpp

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -264,28 +264,25 @@ bool TypeBase::allowsOwnership(const GenericSignatureImpl *sig) {
264264
return getCanonicalType().allowsOwnership(sig);
265265
}
266266

267-
ExistentialLayout::ExistentialLayout(ProtocolType *type) {
268-
assert(type->isCanonical());
269-
267+
ExistentialLayout::ExistentialLayout(CanProtocolType type) {
270268
auto *protoDecl = type->getDecl();
271269

272270
hasExplicitAnyObject = false;
273271
containsNonObjCProtocol = !protoDecl->isObjC();
274272
containsParameterized = false;
275273

276-
singleProtocol = type;
274+
protocols.push_back(protoDecl);
277275
}
278276

279-
ExistentialLayout::ExistentialLayout(ProtocolCompositionType *type) {
280-
assert(type->isCanonical());
281-
277+
ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
282278
hasExplicitAnyObject = type->hasExplicitAnyObject();
283279
containsNonObjCProtocol = false;
284280
containsParameterized = false;
285281

286282
auto members = type.getMembers();
287283
if (!members.empty() &&
288-
isa<ClassDecl>(members[0].getAnyNominal())) {
284+
(members[0].getClassOrBoundGenericClass() ||
285+
isa<UnboundGenericType>(members[0]))) {
289286
explicitSuperclass = members[0];
290287
members = members.slice(1);
291288
}
@@ -300,16 +297,12 @@ ExistentialLayout::ExistentialLayout(ProtocolCompositionType *type) {
300297
containsParameterized = true;
301298
}
302299
containsNonObjCProtocol |= !protoDecl->isObjC();
300+
protocols.push_back(protoDecl);
303301
}
304-
305-
singleProtocol = nullptr;
306-
protocols = { members.data(), members.size() };
307302
}
308303

309-
ExistentialLayout::ExistentialLayout(ParameterizedProtocolType *type) {
310-
assert(type->isCanonical());
311-
312-
*this = ExistentialLayout(type->getBaseType());
304+
ExistentialLayout::ExistentialLayout(CanParameterizedProtocolType type)
305+
: ExistentialLayout(type.getBaseType()) {
313306
sameTypeRequirements = type->getArgs();
314307
containsParameterized = true;
315308
}
@@ -320,10 +313,10 @@ ExistentialLayout TypeBase::getExistentialLayout() {
320313

321314
ExistentialLayout CanType::getExistentialLayout() {
322315
if (auto existential = dyn_cast<ExistentialType>(*this))
323-
return existential->getConstraintType()->getExistentialLayout();
316+
return existential.getConstraintType().getExistentialLayout();
324317

325318
if (auto metatype = dyn_cast<ExistentialMetatypeType>(*this))
326-
return metatype->getInstanceType()->getExistentialLayout();
319+
return metatype.getInstanceType().getExistentialLayout();
327320

328321
if (auto proto = dyn_cast<ProtocolType>(*this))
329322
return ExistentialLayout(proto);
@@ -351,11 +344,10 @@ Type ExistentialLayout::getSuperclass() const {
351344
if (explicitSuperclass)
352345
return explicitSuperclass;
353346

354-
for (auto proto : getProtocols()) {
347+
for (auto protoDecl : getProtocols()) {
355348
// If we have a generic signature, check there, because it
356349
// will pick up superclass constraints from protocols that we
357350
// refine as well.
358-
auto *protoDecl = proto->getDecl();
359351
if (auto genericSig = protoDecl->getGenericSignature()) {
360352
if (auto superclass = genericSig->getSuperclassBound(
361353
protoDecl->getSelfInterfaceType()))
@@ -429,7 +421,7 @@ bool TypeBase::isActorType() {
429421
}
430422

431423
for (auto proto : layout.getProtocols()) {
432-
if (proto->isActorType())
424+
if (proto->isActor())
433425
return true;
434426
}
435427

@@ -464,9 +456,9 @@ bool TypeBase::isDistributedActor() {
464456

465457
auto layout = getExistentialLayout();
466458
return llvm::any_of(layout.getProtocols(),
467-
[&actorProto](ProtocolType *protocol) {
468-
return protocol->getDecl() == actorProto ||
469-
protocol->isDistributedActor();
459+
[&actorProto](ProtocolDecl *protocol) {
460+
return protocol == actorProto ||
461+
protocol->inheritsFrom(actorProto);
470462
});
471463
}
472464

@@ -991,15 +983,14 @@ bool ExistentialLayout::isErrorExistential() const {
991983
return (!hasExplicitAnyObject &&
992984
!explicitSuperclass &&
993985
protocols.size() == 1 &&
994-
protocols[0]->getDecl()->isSpecificProtocol(KnownProtocolKind::Error));
986+
protocols[0]->isSpecificProtocol(KnownProtocolKind::Error));
995987
}
996988

997989
bool ExistentialLayout::isExistentialWithError(ASTContext &ctx) const {
998990
auto errorProto = ctx.getProtocol(KnownProtocolKind::Error);
999991
if (!errorProto) return false;
1000992

1001-
for (auto proto : getProtocols()) {
1002-
auto *protoDecl = proto->getDecl();
993+
for (auto protoDecl : getProtocols()) {
1003994
if (protoDecl == errorProto || protoDecl->inheritsFrom(errorProto))
1004995
return true;
1005996
}
@@ -3971,7 +3962,7 @@ void ParameterizedProtocolType::Profile(llvm::FoldingSetNodeID &ID,
39713962

39723963
void ParameterizedProtocolType::getRequirements(
39733964
Type baseType, SmallVectorImpl<Requirement> &reqs) const {
3974-
auto *protoDecl = getBaseType()->getDecl();
3965+
auto *protoDecl = getProtocol();
39753966

39763967
auto assocTypes = protoDecl->getPrimaryAssociatedTypes();
39773968
auto argTypes = getArgs();

0 commit comments

Comments
 (0)