Skip to content

Commit e7e11df

Browse files
committed
Model Sequence Archetypes
1 parent 7880972 commit e7e11df

22 files changed

+208
-21
lines changed

include/swift/AST/TypeNodes.def

+2-1
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

+49-1
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

+7
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

+1
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

+4
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

+7-2
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

+5
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

+2-1
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

+44-1
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

+1
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;

lib/IRGen/GenType.cpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -1801,14 +1801,15 @@ const TypeInfo &TypeConverter::getCompleteTypeInfo(CanType T) {
18011801

18021802
ArchetypeType *TypeConverter::getExemplarArchetype(ArchetypeType *t) {
18031803
// Get the primary archetype.
1804-
auto primary = dyn_cast<PrimaryArchetypeType>(t->getRoot());
1805-
1804+
auto root = t->getRoot();
1805+
18061806
// If there is no primary (IOW, it's an opened archetype), the archetype is
18071807
// an exemplar.
1808-
if (!primary) return t;
1809-
1808+
if (!isa<PrimaryArchetypeType>(root) && !isa<VariadicSequenceType>(root))
1809+
return t;
1810+
18101811
// Retrieve the generic environment of the archetype.
1811-
auto genericEnv = primary->getGenericEnvironment();
1812+
auto genericEnv = root->getGenericEnvironment();
18121813

18131814
// Dig out the canonical generic environment.
18141815
auto genericSig = genericEnv->getGenericSignature();
@@ -2103,6 +2104,7 @@ const TypeInfo *TypeConverter::convertType(CanType ty) {
21032104
case TypeKind::OpenedArchetype:
21042105
case TypeKind::NestedArchetype:
21052106
case TypeKind::OpaqueTypeArchetype:
2107+
case TypeKind::SequenceArchetype:
21062108
return convertArchetypeType(cast<ArchetypeType>(ty));
21072109
case TypeKind::Class:
21082110
case TypeKind::Enum:
@@ -2557,8 +2559,10 @@ void IRGenFunction::setDynamicSelfMetadata(CanType selfClass,
25572559

25582560
#ifndef NDEBUG
25592561
bool TypeConverter::isExemplarArchetype(ArchetypeType *arch) const {
2560-
auto primary = dyn_cast<PrimaryArchetypeType>(arch->getRoot());
2561-
if (!primary) return true;
2562+
auto primary = arch->getRoot();
2563+
if (!isa<PrimaryArchetypeType>(primary) &&
2564+
!isa<SequenceArchetypeType>(primary))
2565+
return true;
25622566
auto genericEnv = primary->getGenericEnvironment();
25632567

25642568
// Dig out the canonical generic environment.

lib/IRGen/IRGenDebugInfo.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,11 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
851851
return true;
852852
}
853853

854+
if (auto *archetypeTy = t->getAs<SequenceArchetypeType>()) {
855+
Sig = archetypeTy->getGenericEnvironment()->getGenericSignature();
856+
return true;
857+
}
858+
854859
return false;
855860
});
856861

@@ -1518,7 +1523,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
15181523
case TypeKind::OpaqueTypeArchetype:
15191524
case TypeKind::PrimaryArchetype:
15201525
case TypeKind::OpenedArchetype:
1521-
case TypeKind::NestedArchetype: {
1526+
case TypeKind::NestedArchetype:
1527+
case TypeKind::SequenceArchetype: {
15221528
auto *Archetype = BaseTy->castTo<ArchetypeType>();
15231529
AssociatedTypeDecl *assocType = nullptr;
15241530
if (auto nested = dyn_cast<NestedArchetypeType>(Archetype))

lib/IRGen/LocalTypeData.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF,
336336
auto type = dyn_cast<ArchetypeType>(key.Type);
337337
if (!type)
338338
return;
339-
if (!isa<PrimaryArchetypeType>(type))
339+
if (!isa<PrimaryArchetypeType>(type) && !isa<SequenceArchetypeType>(type))
340340
return;
341341

342342
auto *typeParam = type->getInterfaceType()->castTo<GenericTypeParamType>();

lib/IRGen/Outlining.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ irgen::getTypeAndGenericSignatureForManglingOutlineFunction(SILType type) {
118118
loweredType.findIf([&env](Type t) -> bool {
119119
if (auto arch = t->getAs<ArchetypeType>()) {
120120
auto root = arch->getRoot();
121-
if (!isa<PrimaryArchetypeType>(root))
121+
if (!isa<PrimaryArchetypeType>(root) &&
122+
!isa<VariadicSequenceType>(root))
122123
return false;
123124
env = root->getGenericEnvironment();
124125
return true;

lib/SIL/Verifier/SILVerifier.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ static llvm::cl::opt<bool> AllowCriticalEdges("allow-critical-edges",
8686
/// Returns true if A is an opened existential type or is equal to an
8787
/// archetype from F's generic context.
8888
static bool isArchetypeValidInFunction(ArchetypeType *A, const SILFunction *F) {
89-
auto root = dyn_cast<PrimaryArchetypeType>(A->getRoot());
90-
if (!root)
89+
auto root = A->getRoot();
90+
if (!isa<PrimaryArchetypeType>(root) && !isa<SequenceArchetypeType>(root))
9191
return true;
9292
if (isa<OpenedArchetypeType>(A->getRoot()))
9393
return true;

lib/SILOptimizer/Utils/Generics.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,10 @@ shouldBePartiallySpecialized(Type Replacement,
10951095
if (auto Primary = dyn_cast<PrimaryArchetypeType>(Archetype->getRoot())) {
10961096
UsedArchetypes.insert(Primary);
10971097
}
1098+
1099+
if (auto Seq = dyn_cast<SequenceArchetypeType>(Archetype->getRoot())) {
1100+
UsedArchetypes.insert(Seq);
1101+
}
10981102
}
10991103
});
11001104

@@ -1321,6 +1325,10 @@ void FunctionSignaturePartialSpecializer::collectUsedCallerArchetypes(
13211325
if (auto Primary = dyn_cast<PrimaryArchetypeType>(Archetype->getRoot())) {
13221326
UsedCallerArchetypes.insert(Primary);
13231327
}
1328+
1329+
if (auto Seq = dyn_cast<SequenceArchetypeType>(Archetype->getRoot())) {
1330+
UsedCallerArchetypes.insert(Seq);
1331+
}
13241332
}
13251333
});
13261334
}

lib/Sema/CSApply.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -6686,6 +6686,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
66866686
case TypeKind::OpenedArchetype:
66876687
case TypeKind::NestedArchetype:
66886688
case TypeKind::OpaqueTypeArchetype:
6689+
case TypeKind::SequenceArchetype:
66896690
if (!cast<ArchetypeType>(desugaredFromType)->requiresClass())
66906691
break;
66916692
LLVM_FALLTHROUGH;
@@ -7005,6 +7006,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
70057006
case TypeKind::OpenedArchetype:
70067007
case TypeKind::NestedArchetype:
70077008
case TypeKind::OpaqueTypeArchetype:
7009+
case TypeKind::SequenceArchetype:
70087010
case TypeKind::GenericTypeParam:
70097011
case TypeKind::DependentMember:
70107012
case TypeKind::Function:

0 commit comments

Comments
 (0)