Skip to content

Commit a920ba2

Browse files
authored
Merge pull request #38787 from CodaFi/the-nth-degree
Add Sugar for Variadics
2 parents 88e090b + d5953ea commit a920ba2

19 files changed

+108
-32
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/Sema/TypeCheckType.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -359,16 +359,6 @@ bool TypeResolution::areSameType(Type type1, Type type2) const {
359359
return areSameType(depMem1->getBase(), depMem2->getBase());
360360
}
361361

362-
Type TypeChecker::getArraySliceType(SourceLoc loc, Type elementType) {
363-
ASTContext &ctx = elementType->getASTContext();
364-
if (!ctx.getArrayDecl()) {
365-
ctx.Diags.diagnose(loc, diag::sugar_type_not_found, 0);
366-
return ErrorType::get(ctx);
367-
}
368-
369-
return ArraySliceType::get(elementType);
370-
}
371-
372362
Type TypeChecker::getOptionalType(SourceLoc loc, Type elementType) {
373363
ASTContext &ctx = elementType->getASTContext();
374364
if (!ctx.getOptionalDecl()) {
@@ -3604,12 +3594,17 @@ NeverNullType TypeResolver::resolveArrayType(ArrayTypeRepr *repr,
36043594
return ErrorType::get(getASTContext());
36053595
}
36063596

3607-
auto sliceTy =
3608-
TypeChecker::getArraySliceType(repr->getBrackets().Start, baseTy);
3609-
if (sliceTy->hasError())
3610-
return ErrorType::get(getASTContext());
3597+
ASTContext &ctx = baseTy->getASTContext();
3598+
// If the standard library isn't loaded, we ought to let the user know
3599+
// something has gone terribly wrong, since the rest of the compiler is going
3600+
// to assume it can canonicalize [T] to Array<T>.
3601+
if (!ctx.getArrayDecl()) {
3602+
ctx.Diags.diagnose(repr->getBrackets().Start,
3603+
diag::sugar_type_not_found, 0);
3604+
return ErrorType::get(ctx);
3605+
}
36113606

3612-
return sliceTy;
3607+
return ArraySliceType::get(baseTy);
36133608
}
36143609

36153610
NeverNullType

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ enum class CheckedCastContextKind {
231231
};
232232

233233
namespace TypeChecker {
234-
Type getArraySliceType(SourceLoc loc, Type elementType);
235234
Type getOptionalType(SourceLoc loc, Type elementType);
236235

237236
/// Bind an UnresolvedDeclRefExpr by performing name lookup and

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)