Skip to content

Commit 592e90a

Browse files
committed
Add Sugar for Variadics
We used to represent the interface type of variadic parameters directly with ArraySliceType. This was awfully convenient for the constraint solver since it could just canonicalize and open [T] to Array<$T> wherever it saw a variadic parameter. However, this both destroys the sugaring of T... and locks the representation to Array<T>. In the interest of generalizing this in the future, introduce VariadicSequenceType. For now, it canonicalizes to Array<T> just like the old representation. But, as you can guess, this is a new staging point for teaching the solver how to munge variadic generic type bindings. rdar://81628287
1 parent 9f71ee1 commit 592e90a

17 files changed

+98
-16
lines changed

include/swift/AST/TypeNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ ABSTRACT_SUGARED_TYPE(Sugar, Type)
171171
ABSTRACT_SUGARED_TYPE(UnarySyntaxSugar, SyntaxSugarType)
172172
SUGARED_TYPE(ArraySlice, UnarySyntaxSugarType)
173173
SUGARED_TYPE(Optional, UnarySyntaxSugarType)
174-
TYPE_RANGE(UnarySyntaxSugar, ArraySlice, Optional)
174+
SUGARED_TYPE(VariadicSequence, UnarySyntaxSugarType)
175+
TYPE_RANGE(UnarySyntaxSugar, ArraySlice, VariadicSequence)
175176
SUGARED_TYPE(Dictionary, SyntaxSugarType)
176177
TYPE_RANGE(SyntaxSugar, ArraySlice, Dictionary)
177178
TYPE_RANGE(Sugar, Paren, Dictionary)

include/swift/AST/Types.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5045,6 +5045,21 @@ class DictionaryType : public SyntaxSugarType {
50455045
}
50465046
};
50475047

5048+
/// The type T..., which is sugar for a sequence of argument values.
5049+
class VariadicSequenceType : public UnarySyntaxSugarType {
5050+
VariadicSequenceType(const ASTContext &ctx, Type base,
5051+
RecursiveTypeProperties properties)
5052+
: UnarySyntaxSugarType(TypeKind::VariadicSequence, ctx, base, properties) {}
5053+
5054+
public:
5055+
/// Return a uniqued variadic sequence type with the specified base type.
5056+
static VariadicSequenceType *get(Type baseTy);
5057+
5058+
static bool classof(const TypeBase *T) {
5059+
return T->getKind() == TypeKind::VariadicSequence;
5060+
}
5061+
};
5062+
50485063
/// ProtocolType - A protocol type describes an abstract interface implemented
50495064
/// by another type.
50505065
class ProtocolType : public NominalType {
@@ -6239,7 +6254,7 @@ inline bool CanType::isActuallyCanonicalOrNull() const {
62396254

62406255
inline Type TupleTypeElt::getVarargBaseTy() const {
62416256
TypeBase *T = getType().getPointer();
6242-
if (auto *AT = dyn_cast<ArraySliceType>(T))
6257+
if (auto *AT = dyn_cast<VariadicSequenceType>(T))
62436258
return AT->getBaseType();
62446259
if (auto *BGT = dyn_cast<BoundGenericType>(T)) {
62456260
// It's the stdlib Array<T>.

lib/AST/ASTContext.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ struct ASTContext::Implementation {
394394
llvm::DenseMap<llvm::PointerIntPair<TypeBase*, 3, unsigned>,
395395
ExistentialMetatypeType*> ExistentialMetatypeTypes;
396396
llvm::DenseMap<Type, ArraySliceType*> ArraySliceTypes;
397+
llvm::DenseMap<Type, VariadicSequenceType*> VariadicSequenceTypes;
397398
llvm::DenseMap<std::pair<Type, Type>, DictionaryType *> DictionaryTypes;
398399
llvm::DenseMap<Type, OptionalType*> OptionalTypes;
399400
llvm::DenseMap<Type, ParenType*> SimpleParenTypes; // Most are simple
@@ -2569,6 +2570,7 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const {
25692570
llvm::capacity_in_bytes(ArraySliceTypes) +
25702571
llvm::capacity_in_bytes(DictionaryTypes) +
25712572
llvm::capacity_in_bytes(OptionalTypes) +
2573+
llvm::capacity_in_bytes(VariadicSequenceTypes) +
25722574
llvm::capacity_in_bytes(SimpleParenTypes) +
25732575
llvm::capacity_in_bytes(ParenTypes) +
25742576
llvm::capacity_in_bytes(ReferenceStorageTypes) +
@@ -3452,7 +3454,7 @@ Type AnyFunctionType::Param::getParameterType(bool forCanonical,
34523454
else if (forCanonical)
34533455
type = BoundGenericType::get(arrayDecl, Type(), {type});
34543456
else
3455-
type = ArraySliceType::get(type);
3457+
type = VariadicSequenceType::get(type);
34563458
}
34573459
return type;
34583460
}
@@ -4024,6 +4026,18 @@ ArraySliceType *ArraySliceType::get(Type base) {
40244026
return entry = new (C, arena) ArraySliceType(C, base, properties);
40254027
}
40264028

4029+
VariadicSequenceType *VariadicSequenceType::get(Type base) {
4030+
auto properties = base->getRecursiveProperties();
4031+
auto arena = getArena(properties);
4032+
4033+
const ASTContext &C = base->getASTContext();
4034+
4035+
VariadicSequenceType *&entry = C.getImpl().getArena(arena).VariadicSequenceTypes[base];
4036+
if (entry) return entry;
4037+
4038+
return entry = new (C, arena) VariadicSequenceType(C, base, properties);
4039+
}
4040+
40274041
DictionaryType *DictionaryType::get(Type keyType, Type valueType) {
40284042
auto properties = keyType->getRecursiveProperties()
40294043
| valueType->getRecursiveProperties();

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3840,6 +3840,12 @@ namespace {
38403840
PrintWithColorRAII(OS, ParenthesisColor) << ')';
38413841
}
38423842

3843+
void visitVariadicSequenceType(VariadicSequenceType *T, StringRef label) {
3844+
printCommon(label, "variadic_sequence_type");
3845+
printRec(T->getBaseType());
3846+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3847+
}
3848+
38433849
void visitProtocolCompositionType(ProtocolCompositionType *T,
38443850
StringRef label) {
38453851
printCommon(label, "protocol_composition_type");

lib/AST/ASTMangler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,12 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
11321132
appendOperator("XSa");
11331133
return;
11341134

1135+
case TypeKind::VariadicSequence:
1136+
assert(DWARFMangling && "sugared types are only legal for the debugger");
1137+
appendType(cast<VariadicSequenceType>(tybase)->getBaseType());
1138+
appendOperator("XSa");
1139+
return;
1140+
11351141
case TypeKind::Optional:
11361142
assert(DWARFMangling && "sugared types are only legal for the debugger");
11371143
appendType(cast<OptionalType>(tybase)->getBaseType());

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5128,6 +5128,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
51285128
Printer << "?";
51295129
}
51305130

5131+
void visitVariadicSequenceType(VariadicSequenceType *T) {
5132+
visit(T->getBaseType());
5133+
Printer << "...";
5134+
}
5135+
51315136
void visitProtocolType(ProtocolType *T) {
51325137
printQualifiedType(T);
51335138
}

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6528,7 +6528,7 @@ void ParamDecl::setNonEphemeralIfPossible() {
65286528

65296529
Type ParamDecl::getVarargBaseTy(Type VarArgT) {
65306530
TypeBase *T = VarArgT.getPointer();
6531-
if (auto *AT = dyn_cast<ArraySliceType>(T))
6531+
if (auto *AT = dyn_cast<VariadicSequenceType>(T))
65326532
return AT->getBaseType();
65336533
if (auto *BGT = dyn_cast<BoundGenericType>(T)) {
65346534
// It's the stdlib Array<T>.

lib/AST/Type.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,7 @@ Type SugarType::getSinglyDesugaredTypeSlow() {
15611561
case TypeKind::TypeAlias:
15621562
llvm_unreachable("bound type alias types always have an underlying type");
15631563
case TypeKind::ArraySlice:
1564+
case TypeKind::VariadicSequence:
15641565
implDecl = Context->getArrayDecl();
15651566
break;
15661567
case TypeKind::Optional:
@@ -4974,6 +4975,18 @@ case TypeKind::Id:
49744975
return OptionalType::get(baseTy);
49754976
}
49764977

4978+
case TypeKind::VariadicSequence: {
4979+
auto seq = cast<VariadicSequenceType>(base);
4980+
auto baseTy = seq->getBaseType().transformRec(fn);
4981+
if (!baseTy)
4982+
return Type();
4983+
4984+
if (baseTy.getPointer() == seq->getBaseType().getPointer())
4985+
return *this;
4986+
4987+
return VariadicSequenceType::get(baseTy);
4988+
}
4989+
49774990
case TypeKind::Dictionary: {
49784991
auto dict = cast<DictionaryType>(base);
49794992
auto keyTy = dict->getKeyType().transformRec(fn);

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1629,7 +1629,8 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
16291629
// SyntaxSugarType derivations.
16301630
case TypeKind::Dictionary:
16311631
case TypeKind::ArraySlice:
1632-
case TypeKind::Optional: {
1632+
case TypeKind::Optional:
1633+
case TypeKind::VariadicSequence: {
16331634
auto *SyntaxSugarTy = cast<SyntaxSugarType>(BaseTy);
16341635
auto *CanTy = SyntaxSugarTy->getSinglyDesugaredType();
16351636
return getOrCreateDesugaredType(CanTy, DbgTy);

lib/Sema/CSGen.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,14 +2623,13 @@ namespace {
26232623

26242624
// Try to build the appropriate type for a variadic argument list of
26252625
// the fresh element type. If that failed, just bail out.
2626-
auto array = TypeChecker::getArraySliceType(expr->getLoc(), element);
2627-
if (array->hasError()) return element;
2626+
auto variadicSeq = VariadicSequenceType::get(element);
26282627

26292628
// Require the operand to be convertible to the array type.
26302629
CS.addConstraint(ConstraintKind::Conversion,
2631-
CS.getType(expr->getSubExpr()), array,
2630+
CS.getType(expr->getSubExpr()), variadicSeq,
26322631
CS.getConstraintLocator(expr));
2633-
return array;
2632+
return variadicSeq;
26342633
}
26352634

26362635
Type visitDynamicTypeExpr(DynamicTypeExpr *expr) {

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8900,7 +8900,7 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
89008900
// If external parameter is variadic it translates into an array in
89018901
// the body of the closure.
89028902
internalType =
8903-
param.isVariadic() ? ArraySliceType::get(typeVar) : Type(typeVar);
8903+
param.isVariadic() ? VariadicSequenceType::get(typeVar) : Type(typeVar);
89048904

89058905
auto externalType = param.getOldType();
89068906

lib/Sema/TypeCheckDecl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,9 +2166,10 @@ static Type validateParameterType(ParamDecl *decl) {
21662166
}
21672167

21682168
if (decl->isVariadic()) {
2169-
Ty = TypeChecker::getArraySliceType(decl->getStartLoc(), Ty);
2170-
if (Ty->hasError()) {
2171-
decl->setInvalid();
2169+
Ty = VariadicSequenceType::get(Ty);
2170+
if (!ctx.getArrayDecl()) {
2171+
ctx.Diags.diagnose(decl->getTypeRepr()->getLoc(),
2172+
diag::sugar_type_not_found, 0);
21722173
return ErrorType::get(ctx);
21732174
}
21742175

lib/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ TYPE(DICTIONARY)
101101
TYPE(REFERENCE_STORAGE)
102102
TYPE(UNBOUND_GENERIC)
103103
TYPE(OPTIONAL)
104+
TYPE(VARIADIC_SEQUENCE)
104105
TYPE(SIL_FUNCTION)
105106
TYPE(DYNAMIC_SELF)
106107
TYPE(OPENED_EXISTENTIAL)

lib/Serialization/Deserialization.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5901,6 +5901,18 @@ class TypeDeserializer {
59015901
return OptionalType::get(baseTy.get());
59025902
}
59035903

5904+
Expected<Type> deserializeVariadicSequenceType(ArrayRef<uint64_t> scratch,
5905+
StringRef blobData) {
5906+
TypeID baseID;
5907+
decls_block::VariadicSequenceTypeLayout::readRecord(scratch, baseID);
5908+
5909+
auto baseTy = MF.getTypeChecked(baseID);
5910+
if (!baseTy)
5911+
return baseTy.takeError();
5912+
5913+
return VariadicSequenceType::get(baseTy.get());
5914+
}
5915+
59045916
Expected<Type> deserializeUnboundGenericType(ArrayRef<uint64_t> scratch,
59055917
StringRef blobData) {
59065918
DeclID genericID;
@@ -6024,6 +6036,7 @@ Expected<Type> TypeDeserializer::getTypeCheckedImpl() {
60246036
CASE(ArraySlice)
60256037
CASE(Dictionary)
60266038
CASE(Optional)
6039+
CASE(VariadicSequence)
60276040
CASE(UnboundGeneric)
60286041
CASE(Error)
60296042

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,7 @@ namespace decls_block {
11451145

11461146
using ArraySliceTypeLayout = SyntaxSugarTypeLayout<ARRAY_SLICE_TYPE>;
11471147
using OptionalTypeLayout = SyntaxSugarTypeLayout<OPTIONAL_TYPE>;
1148+
using VariadicSequenceTypeLayout = SyntaxSugarTypeLayout<VARIADIC_SEQUENCE_TYPE>;
11481149

11491150
using DictionaryTypeLayout = BCRecordLayout<
11501151
DICTIONARY_TYPE,

lib/Serialization/Serialization.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4544,6 +4544,11 @@ class Serializer::TypeSerializer : public TypeVisitor<TypeSerializer> {
45444544
S.addTypeRef(dictTy->getValueType()));
45454545
}
45464546

4547+
void visitVariadicSequenceType(const VariadicSequenceType *seqTy) {
4548+
using namespace decls_block;
4549+
serializeSimpleWrapper<VariadicSequenceTypeLayout>(seqTy->getBaseType());
4550+
}
4551+
45474552
void visitOptionalType(const OptionalType *optionalTy) {
45484553
using namespace decls_block;
45494554
serializeSimpleWrapper<OptionalTypeLayout>(optionalTy->getBaseType());
@@ -4747,6 +4752,7 @@ void Serializer::writeAllDeclsAndTypes() {
47474752
registerDeclTypeAbbr<SILFunctionTypeLayout>();
47484753
registerDeclTypeAbbr<ArraySliceTypeLayout>();
47494754
registerDeclTypeAbbr<DictionaryTypeLayout>();
4755+
registerDeclTypeAbbr<VariadicSequenceTypeLayout>();
47504756
registerDeclTypeAbbr<ReferenceStorageTypeLayout>();
47514757
registerDeclTypeAbbr<UnboundGenericTypeLayout>();
47524758
registerDeclTypeAbbr<OptionalTypeLayout>();

test/Constraints/keypath.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ func testVariadicKeypathAsFunc() {
7878
takesVariadicFnWithGenericRet(\Array.i)
7979

8080
// These are not okay, the KeyPath should have a base that matches the
81-
// internal parameter type of the function, i.e [S].
82-
let _: (S...) -> Int = \S.i // expected-error {{key path value type 'S' cannot be converted to contextual type '[S]'}}
83-
takesVariadicFnWithGenericRet(\S.i) // expected-error {{key path value type 'S' cannot be converted to contextual type '[S]'}}
81+
// internal parameter type of the function, i.e (S...).
82+
let _: (S...) -> Int = \S.i // expected-error {{key path value type 'S' cannot be converted to contextual type 'S...'}}
83+
takesVariadicFnWithGenericRet(\S.i) // expected-error {{key path value type 'S' cannot be converted to contextual type 'S...'}}
8484
}
8585

8686
// rdar://problem/54322807

0 commit comments

Comments
 (0)