Skip to content

Commit 1faf7ed

Browse files
authored
Merge pull request #40193 from CodaFi/sequential-access-patterns
Model Sequence Archetypes
2 parents 63f355f + e7e11df commit 1faf7ed

22 files changed

+208
-21
lines changed

include/swift/AST/TypeNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ ABSTRACT_TYPE(Substitutable, Type)
148148
ALWAYS_CANONICAL_TYPE(OpaqueTypeArchetype, ArchetypeType)
149149
ALWAYS_CANONICAL_TYPE(OpenedArchetype, ArchetypeType)
150150
ALWAYS_CANONICAL_TYPE(NestedArchetype, ArchetypeType)
151-
TYPE_RANGE(Archetype, PrimaryArchetype, NestedArchetype)
151+
ALWAYS_CANONICAL_TYPE(SequenceArchetype, ArchetypeType)
152+
TYPE_RANGE(Archetype, PrimaryArchetype, SequenceArchetype)
152153
TYPE(GenericTypeParam, SubstitutableType)
153154
TYPE_RANGE(Substitutable, PrimaryArchetype, GenericTypeParam)
154155
TYPE(DependentMember, Type)

include/swift/AST/Types.h

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ class RecursiveTypeProperties {
124124
HasTypeVariable = 0x01,
125125

126126
/// This type expression contains a context-dependent archetype, either a
127-
/// PrimaryArchetypeType or OpenedArchetypeType.
127+
/// \c PrimaryArchetypeType, \c OpenedArchetypeType, or
128+
/// \c SequenceArchetype.
128129
HasArchetype = 0x02,
129130

130131
/// This type expression contains a GenericTypeParamType.
@@ -5683,6 +5684,50 @@ CanArchetypeType getParent() const {
56835684
}
56845685
END_CAN_TYPE_WRAPPER(NestedArchetypeType, ArchetypeType)
56855686

5687+
/// An archetype that represents an opaque element of a type sequence in context.
5688+
///
5689+
/// \code
5690+
/// struct Foo<@_typeSequence Ts> { var xs: @_typeSequence Ts }
5691+
/// func foo<@_typeSequence T>(_ xs: T...) where T: P { }
5692+
/// \endcode
5693+
class SequenceArchetypeType final
5694+
: public ArchetypeType,
5695+
private ArchetypeTrailingObjects<SequenceArchetypeType> {
5696+
friend TrailingObjects;
5697+
friend ArchetypeType;
5698+
5699+
GenericEnvironment *Environment;
5700+
5701+
public:
5702+
/// getNew - Create a new sequence archetype with the given name.
5703+
///
5704+
/// The ConformsTo array will be minimized then copied into the ASTContext
5705+
/// by this routine.
5706+
static CanTypeWrapper<SequenceArchetypeType>
5707+
get(const ASTContext &Ctx, GenericEnvironment *GenericEnv,
5708+
GenericTypeParamType *InterfaceType,
5709+
SmallVectorImpl<ProtocolDecl *> &ConformsTo, Type Superclass,
5710+
LayoutConstraint Layout);
5711+
5712+
/// Retrieve the generic environment in which this archetype resides.
5713+
GenericEnvironment *getGenericEnvironment() const { return Environment; }
5714+
5715+
GenericTypeParamType *getInterfaceType() const {
5716+
return cast<GenericTypeParamType>(InterfaceType.getPointer());
5717+
}
5718+
5719+
static bool classof(const TypeBase *T) {
5720+
return T->getKind() == TypeKind::SequenceArchetype;
5721+
}
5722+
5723+
private:
5724+
SequenceArchetypeType(const ASTContext &Ctx, GenericEnvironment *GenericEnv,
5725+
Type InterfaceType, ArrayRef<ProtocolDecl *> ConformsTo,
5726+
Type Superclass, LayoutConstraint Layout);
5727+
};
5728+
BEGIN_CAN_TYPE_WRAPPER(SequenceArchetypeType, ArchetypeType)
5729+
END_CAN_TYPE_WRAPPER(SequenceArchetypeType, ArchetypeType)
5730+
56865731
template<typename Type>
56875732
const Type *ArchetypeType::getSubclassTrailingObjects() const {
56885733
if (auto contextTy = dyn_cast<PrimaryArchetypeType>(this)) {
@@ -5697,6 +5742,9 @@ const Type *ArchetypeType::getSubclassTrailingObjects() const {
56975742
if (auto childTy = dyn_cast<NestedArchetypeType>(this)) {
56985743
return childTy->getTrailingObjects<Type>();
56995744
}
5745+
if (auto childTy = dyn_cast<SequenceArchetypeType>(this)) {
5746+
return childTy->getTrailingObjects<Type>();
5747+
}
57005748
llvm_unreachable("unhandled ArchetypeType subclass?");
57015749
}
57025750

lib/AST/ASTDumper.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3732,6 +3732,13 @@ namespace {
37323732
printArchetypeNestedTypes(T);
37333733
PrintWithColorRAII(OS, ParenthesisColor) << ')';
37343734
}
3735+
void visitSequenceArchetypeType(SequenceArchetypeType *T, StringRef label) {
3736+
printArchetypeCommon(T, "sequence_archetype_type", label);
3737+
printField("name", T->getFullName());
3738+
OS << "\n";
3739+
printArchetypeNestedTypes(T);
3740+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3741+
}
37353742

37363743
void visitGenericTypeParamType(GenericTypeParamType *T, StringRef label) {
37373744
printCommon(label, "generic_type_param_type");

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,7 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
12931293
// type ::= archetype
12941294
case TypeKind::PrimaryArchetype:
12951295
case TypeKind::OpenedArchetype:
1296+
case TypeKind::SequenceArchetype:
12961297
llvm_unreachable("Cannot mangle free-standing archetypes");
12971298

12981299
case TypeKind::OpaqueTypeArchetype: {

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5397,6 +5397,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
53975397
}
53985398
}
53995399

5400+
void visitSequenceArchetypeType(SequenceArchetypeType *T) {
5401+
printArchetypeCommon(T, T->getInterfaceType()->getDecl());
5402+
}
5403+
54005404
void visitGenericTypeParamType(GenericTypeParamType *T) {
54015405
if (T->getDecl() == nullptr) {
54025406
// If we have an alternate name for this type, use it.

lib/AST/ASTVerifier.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,8 +618,13 @@ class Verifier : public ASTWalker {
618618
}
619619

620620
// Get the archetype's generic signature.
621-
auto rootPrimary = cast<PrimaryArchetypeType>(root);
622-
auto *archetypeEnv = rootPrimary->getGenericEnvironment();
621+
GenericEnvironment *archetypeEnv;
622+
if (auto seq = dyn_cast<SequenceArchetypeType>(root)) {
623+
archetypeEnv = seq->getGenericEnvironment();
624+
} else {
625+
auto rootPrimary = cast<PrimaryArchetypeType>(root);
626+
archetypeEnv = rootPrimary->getGenericEnvironment();
627+
}
623628
auto archetypeSig = archetypeEnv->getGenericSignature();
624629

625630
auto genericCtx = Generics.back();

lib/AST/GenericEnvironment.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
167167
requirements.protos, superclass,
168168
requirements.layout);
169169
parentArchetype->registerNestedType(depMemTy->getName(), result);
170+
} else if (genericParam->isTypeSequence()) {
171+
result = SequenceArchetypeType::get(ctx, this, genericParam,
172+
requirements.protos, superclass,
173+
requirements.layout);
174+
addMapping(genericParam, result);
170175
} else {
171176
result = PrimaryArchetypeType::getNew(ctx, this, genericParam,
172177
requirements.protos, superclass,

lib/AST/SubstitutionMap.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const {
249249
// If we have an archetype, map out of the context so we can compute a
250250
// conformance access path.
251251
if (auto archetype = dyn_cast<ArchetypeType>(type)) {
252-
if (!isa<PrimaryArchetypeType>(archetype))
252+
if (!isa<PrimaryArchetypeType>(archetype) &&
253+
!isa<SequenceArchetypeType>(archetype))
253254
return Type();
254255

255256
type = cast<GenericTypeParamType>(

lib/AST/Type.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ bool CanType::isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig,
184184
case TypeKind::OpenedArchetype:
185185
case TypeKind::NestedArchetype:
186186
case TypeKind::OpaqueTypeArchetype:
187+
case TypeKind::SequenceArchetype:
187188
return cast<ArchetypeType>(type)->requiresClass();
188189
case TypeKind::Protocol:
189190
return cast<ProtocolType>(type)->requiresClass();
@@ -3062,6 +3063,9 @@ GenericEnvironment *ArchetypeType::getGenericEnvironment() const {
30623063
if (auto opaque = dyn_cast<OpaqueTypeArchetypeType>(root)) {
30633064
return opaque->getGenericEnvironment();
30643065
}
3066+
if (auto opaque = dyn_cast<SequenceArchetypeType>(root)) {
3067+
return opaque->getGenericEnvironment();
3068+
}
30653069
llvm_unreachable("unhandled root archetype kind?!");
30663070
}
30673071

@@ -3145,6 +3149,17 @@ OpaqueTypeArchetypeType::OpaqueTypeArchetypeType(OpaqueTypeDecl *OpaqueDecl,
31453149
{
31463150
}
31473151

3152+
SequenceArchetypeType::SequenceArchetypeType(
3153+
const ASTContext &Ctx, GenericEnvironment *GenericEnv, Type InterfaceType,
3154+
ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,
3155+
LayoutConstraint Layout)
3156+
: ArchetypeType(TypeKind::SequenceArchetype, Ctx,
3157+
RecursiveTypeProperties::HasArchetype, InterfaceType,
3158+
ConformsTo, Superclass, Layout),
3159+
Environment(GenericEnv) {
3160+
assert(cast<GenericTypeParamType>(InterfaceType.getPointer())->isTypeSequence());
3161+
}
3162+
31483163
GenericSignature OpaqueTypeArchetypeType::getBoundSignature() const {
31493164
return Environment->getGenericSignature();
31503165
}
@@ -3459,6 +3474,29 @@ PrimaryArchetypeType::getNew(const ASTContext &Ctx,
34593474
Ctx, GenericEnv, InterfaceType, ConformsTo, Superclass, Layout));
34603475
}
34613476

3477+
CanSequenceArchetypeType
3478+
SequenceArchetypeType::get(const ASTContext &Ctx,
3479+
GenericEnvironment *GenericEnv,
3480+
GenericTypeParamType *InterfaceType,
3481+
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
3482+
Type Superclass, LayoutConstraint Layout) {
3483+
assert(!Superclass || Superclass->getClassOrBoundGenericClass());
3484+
assert(GenericEnv && "missing generic environment for archetype");
3485+
3486+
// Gather the set of protocol declarations to which this archetype conforms.
3487+
ProtocolType::canonicalizeProtocols(ConformsTo);
3488+
3489+
auto arena = AllocationArena::Permanent;
3490+
void *mem =
3491+
Ctx.Allocate(SequenceArchetypeType::totalSizeToAlloc<ProtocolDecl *, Type,
3492+
LayoutConstraint>(
3493+
ConformsTo.size(), Superclass ? 1 : 0, Layout ? 1 : 0),
3494+
alignof(SequenceArchetypeType), arena);
3495+
3496+
return CanSequenceArchetypeType(::new (mem) SequenceArchetypeType(
3497+
Ctx, GenericEnv, InterfaceType, ConformsTo, Superclass, Layout));
3498+
}
3499+
34623500
bool ArchetypeType::requiresClass() const {
34633501
if (auto layout = getLayoutConstraint())
34643502
return layout->isClass();
@@ -4125,6 +4163,9 @@ static Type substType(Type derivedType,
41254163
if (isa<PrimaryArchetypeType>(substOrig))
41264164
return ErrorType::get(type);
41274165

4166+
if (isa<SequenceArchetypeType>(substOrig))
4167+
return ErrorType::get(type);
4168+
41284169
// Opened existentials cannot be substituted in this manner,
41294170
// but if they appear in the original type this is not an
41304171
// error.
@@ -4534,6 +4575,7 @@ case TypeKind::Id:
45344575
#include "swift/AST/TypeNodes.def"
45354576
case TypeKind::PrimaryArchetype:
45364577
case TypeKind::OpenedArchetype:
4578+
case TypeKind::SequenceArchetype:
45374579
case TypeKind::Error:
45384580
case TypeKind::Unresolved:
45394581
case TypeKind::TypeVariable:
@@ -5279,7 +5321,8 @@ ReferenceCounting TypeBase::getReferenceCounting() {
52795321
case TypeKind::PrimaryArchetype:
52805322
case TypeKind::OpenedArchetype:
52815323
case TypeKind::NestedArchetype:
5282-
case TypeKind::OpaqueTypeArchetype: {
5324+
case TypeKind::OpaqueTypeArchetype:
5325+
case TypeKind::SequenceArchetype: {
52835326
auto archetype = cast<ArchetypeType>(type);
52845327
auto layout = archetype->getLayoutConstraint();
52855328
(void)layout;

lib/IRGen/Fulfillment.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ static bool isLeafTypeMetadata(CanType type) {
6868
case TypeKind::OpenedArchetype:
6969
case TypeKind::NestedArchetype:
7070
case TypeKind::OpaqueTypeArchetype:
71+
case TypeKind::SequenceArchetype:
7172
case TypeKind::GenericTypeParam:
7273
case TypeKind::DependentMember:
7374
return true;

0 commit comments

Comments
 (0)