Skip to content

Commit f00e5bc

Browse files
committed
Allow a variadic parameter anywhere in the parameter list.
Requiring a variadic parameter to come at the end of the parameter list is an old restriction that makes no sense nowadays, and which we had all thought we had already lifted. It made variadic parameters unusable with trailing closures or defaulted arguments, and made our new print() design unimplementable. Remove this restriction, replacing it with a less onerous and slightly less silly restriction that we not have more than one variadic parameter in a given parameter clause. Fixes rdar://problem/20127197. Swift SVN r30542
1 parent fdc927e commit f00e5bc

36 files changed

+388
-255
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,8 @@ ERROR(expected_rbracket_dictionary_type,type_parsing,PointsToFirstBadToken,
609609
// Tuple Types
610610
ERROR(expected_rparen_tuple_type_list,type_parsing,none,
611611
"expected ')' at end of tuple list", ())
612-
ERROR(empty_tuple_ellipsis,type_parsing,none,
613-
"varargs used in tuple type with no fields", ())
614-
ERROR(unexpected_ellipsis_in_tuple,type_parsing,none,
615-
"unexpected '...' before the end of a tuple list", ())
612+
ERROR(multiple_ellipsis_in_tuple,type_parsing,none,
613+
"only a single element can be variadic", ())
616614
ERROR(tuple_type_init,pattern_parsing,none,
617615
"default argument not permitted in a tuple type", ())
618616
ERROR(protocol_method_argument_init,type_parsing,none,
@@ -653,8 +651,8 @@ ERROR(expected_rparen_parameter,decl_parsing,PointsToFirstBadToken,
653651
"expected ')' in parameter", ())
654652
ERROR(expected_parameter_type,decl_parsing,PointsToFirstBadToken,
655653
"expected parameter type following ':'", ())
656-
ERROR(parameter_ellipsis_not_at_end,decl_parsing,none,
657-
"'...' must be on the last parameter", ())
654+
ERROR(multiple_parameter_ellipsis,decl_parsing,none,
655+
"only a single variadic parameter '...' is permitted", ())
658656
ERROR(parameter_vararg_default,decl_parsing,none,
659657
"variadic parameter cannot have a default value", ())
660658
ERROR(parameter_backtick_missing_name,decl_parsing,PointsToFirstBadToken,

include/swift/AST/Expr.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,8 +2259,8 @@ class TupleShuffleExpr : public ImplicitConversionExpr {
22592259
/// The element mapping value indicating that a field of the destination
22602260
/// tuple should be default-initialized.
22612261
DefaultInitialize = -1,
2262-
/// The element mapping value signaling the first variadic field.
2263-
FirstVariadic = -2,
2262+
/// The element mapping is part of the variadic field.
2263+
Variadic = -2,
22642264
/// The element mapping value indicating that the field of the
22652265
/// destination tuple should be default-initialized with an expression
22662266
/// provided by the caller.
@@ -2288,16 +2288,21 @@ class TupleShuffleExpr : public ImplicitConversionExpr {
22882288
/// declaration.
22892289
ConcreteDeclRef DefaultArgsOwner;
22902290

2291+
/// The arguments that are packed into the variadic element.
2292+
ArrayRef<unsigned> VariadicArgs;
2293+
22912294
MutableArrayRef<Expr *> CallerDefaultArgs;
22922295

22932296
public:
22942297
TupleShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
22952298
SourceIsScalar_t isSourceScalar,
22962299
ConcreteDeclRef defaultArgsOwner,
2300+
ArrayRef<unsigned> VariadicArgs,
22972301
MutableArrayRef<Expr *> CallerDefaultArgs, Type ty)
22982302
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty),
22992303
ElementMapping(elementMapping), VarargsArrayTy(),
2300-
DefaultArgsOwner(defaultArgsOwner), CallerDefaultArgs(CallerDefaultArgs)
2304+
DefaultArgsOwner(defaultArgsOwner), VariadicArgs(VariadicArgs),
2305+
CallerDefaultArgs(CallerDefaultArgs)
23012306
{
23022307
TupleShuffleExprBits.IsSourceScalar = isSourceScalar;
23032308
}
@@ -2321,6 +2326,9 @@ class TupleShuffleExpr : public ImplicitConversionExpr {
23212326
return VarargsArrayTy;
23222327
}
23232328

2329+
/// Retrieve the argument indices for the variadic arguments.
2330+
ArrayRef<unsigned> getVariadicArgs() const { return VariadicArgs; }
2331+
23242332
/// Retrieve the owner of the default arguments.
23252333
ConcreteDeclRef getDefaultArgsOwner() const { return DefaultArgsOwner; }
23262334

include/swift/AST/Pattern.h

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ class alignas(8) Pattern {
5555
class TuplePatternBitfields {
5656
friend class TuplePattern;
5757
unsigned : NumPatternBits;
58-
unsigned HasVararg : 1;
59-
unsigned NumElements : NumBitsAllocated - NumPatternBits - 1;
58+
unsigned NumElements : NumBitsAllocated - NumPatternBits;
6059
};
6160

6261
class TypedPatternBitfields {
@@ -272,20 +271,23 @@ class ParenPattern : public Pattern {
272271
class TuplePatternElt {
273272
Identifier Label;
274273
SourceLoc LabelLoc;
275-
Pattern *ThePattern;
274+
llvm::PointerIntPair<Pattern *, 1, bool> ThePatternAndEllipsis;
275+
SourceLoc EllipsisLoc;
276276
ExprHandle *Init;
277277
DefaultArgumentKind DefArgKind;
278278

279279
public:
280280
TuplePatternElt() = default;
281281
explicit TuplePatternElt(Pattern *P)
282-
: ThePattern(P), Init(nullptr), DefArgKind(DefaultArgumentKind::None) {}
282+
: ThePatternAndEllipsis(P, false), Init(nullptr), DefArgKind(DefaultArgumentKind::None) {}
283283

284284
TuplePatternElt(Identifier Label, SourceLoc LabelLoc,
285-
Pattern *p, ExprHandle *init = nullptr,
285+
Pattern *p, bool hasEllipsis,
286+
SourceLoc ellipsisLoc = SourceLoc(),
287+
ExprHandle *init = nullptr,
286288
DefaultArgumentKind defArgKind = DefaultArgumentKind::None)
287-
: Label(Label), LabelLoc(LabelLoc),
288-
ThePattern(p), Init(init), DefArgKind(defArgKind) {}
289+
: Label(Label), LabelLoc(LabelLoc), ThePatternAndEllipsis(p, hasEllipsis),
290+
EllipsisLoc(ellipsisLoc), Init(init), DefArgKind(defArgKind) {}
289291

290292
Identifier getLabel() const { return Label; }
291293
SourceLoc getLabelLoc() const { return LabelLoc; }
@@ -294,9 +296,15 @@ class TuplePatternElt {
294296
LabelLoc = Loc;
295297
}
296298

297-
Pattern *getPattern() { return ThePattern; }
298-
const Pattern *getPattern() const { return ThePattern; }
299-
void setPattern(Pattern *p) { ThePattern = p; }
299+
Pattern *getPattern() { return ThePatternAndEllipsis.getPointer(); }
300+
const Pattern *getPattern() const {
301+
return ThePatternAndEllipsis.getPointer();
302+
}
303+
304+
void setPattern(Pattern *p) { ThePatternAndEllipsis.setPointer(p); }
305+
306+
bool hasEllipsis() const { return ThePatternAndEllipsis.getInt(); }
307+
SourceLoc getEllipsisLoc() const { return EllipsisLoc; }
300308

301309
ExprHandle *getInit() const { return Init; }
302310

@@ -307,7 +315,6 @@ class TuplePatternElt {
307315
/// A pattern consisting of a tuple of patterns.
308316
class TuplePattern : public Pattern {
309317
SourceLoc LPLoc, RPLoc;
310-
// TuplePatternBits.HasVararg
311318
// TuplePatternBits.NumElements
312319

313320
TuplePatternElt *getElementsBuffer() {
@@ -317,23 +324,10 @@ class TuplePattern : public Pattern {
317324
return reinterpret_cast<const TuplePatternElt *>(this + 1);
318325
}
319326

320-
SourceLoc *getEllipsisLocPtr() {
321-
assert(TuplePatternBits.HasVararg);
322-
return reinterpret_cast<SourceLoc *>(getElementsBuffer()+getNumElements());
323-
}
324-
const SourceLoc *getEllipsisLocPtr() const {
325-
assert(TuplePatternBits.HasVararg);
326-
return reinterpret_cast<const SourceLoc *>
327-
(getElementsBuffer()+getNumElements());
328-
}
329-
330-
TuplePattern(SourceLoc lp, unsigned numElements, SourceLoc rp, bool hasVararg,
331-
SourceLoc ellipsis, bool implicit)
327+
TuplePattern(SourceLoc lp, unsigned numElements, SourceLoc rp,
328+
bool implicit)
332329
: Pattern(PatternKind::Tuple), LPLoc(lp), RPLoc(rp) {
333330
TuplePatternBits.NumElements = numElements;
334-
TuplePatternBits.HasVararg = hasVararg;
335-
if (hasVararg)
336-
*getEllipsisLocPtr() = ellipsis;
337331
assert(lp.isValid() == rp.isValid());
338332
if (implicit)
339333
setImplicit();
@@ -342,16 +336,12 @@ class TuplePattern : public Pattern {
342336
public:
343337
static TuplePattern *create(ASTContext &C, SourceLoc lp,
344338
ArrayRef<TuplePatternElt> elements, SourceLoc rp,
345-
bool hasVararg = false,
346-
SourceLoc ellipsis = SourceLoc(),
347339
Optional<bool> implicit = None);
348340

349341
/// \brief Create either a tuple pattern or a paren pattern, depending
350342
/// on the elements.
351343
static Pattern *createSimple(ASTContext &C, SourceLoc lp,
352344
ArrayRef<TuplePatternElt> elements, SourceLoc rp,
353-
bool hasVararg = false,
354-
SourceLoc ellipsis = SourceLoc(),
355345
Optional<bool> implicit = None);
356346

357347
unsigned getNumElements() const {
@@ -369,16 +359,12 @@ class TuplePattern : public Pattern {
369359
const TuplePatternElt &getElement(unsigned i) const {return getElements()[i];}
370360
TuplePatternElt &getElement(unsigned i) { return getElements()[i]; }
371361

372-
bool hasVararg() const { return TuplePatternBits.HasVararg; }
373-
374362
SourceLoc getLParenLoc() const { return LPLoc; }
375363
SourceLoc getRParenLoc() const { return RPLoc; }
376364
SourceRange getSourceRange() const;
377-
SourceLoc getEllipsisLoc() const {
378-
if (hasVararg())
379-
return *getEllipsisLocPtr();
380-
return SourceLoc();
381-
}
365+
366+
bool hasAnyEllipsis() const;
367+
SourceLoc getAnyEllipsisLoc() const;
382368

383369
static bool classof(const Pattern *P) {
384370
return P->getKind() == PatternKind::Tuple;

include/swift/AST/TypeRepr.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -511,28 +511,34 @@ class TupleTypeRepr : public TypeRepr {
511511
SourceRange Parens;
512512
// FIXME: Tail allocation.
513513
SourceLoc Ellipsis;
514+
unsigned EllipsisIdx;
514515

515516
public:
516517
TupleTypeRepr(ArrayRef<TypeRepr *> Elements, SourceRange Parens,
517-
SourceLoc Ellipsis)
518+
SourceLoc Ellipsis, unsigned EllipsisIdx)
518519
: TypeRepr(TypeReprKind::Tuple), Elements(Elements),
519-
Parens(Parens), Ellipsis(Ellipsis) {
520+
Parens(Parens), Ellipsis(Ellipsis), EllipsisIdx(EllipsisIdx) {
520521
}
521522

522523
ArrayRef<TypeRepr *> getElements() const { return Elements; }
523524
TypeRepr *getElement(unsigned i) const { return Elements[i]; }
524525
SourceRange getParens() const { return Parens; }
525526
SourceLoc getEllipsisLoc() const { return Ellipsis; }
527+
unsigned getEllipsisIndex() const { return EllipsisIdx; }
526528
bool hasEllipsis() const { return Ellipsis.isValid(); }
527529

528-
void removeEllipsis() { Ellipsis = SourceLoc(); }
530+
void removeEllipsis() {
531+
Ellipsis = SourceLoc();
532+
EllipsisIdx = Elements.size();
533+
}
529534

530535
bool isParenType() const {
531536
return Elements.size() == 1 && !isa<NamedTypeRepr>(Elements[0]);
532537
}
533538

534539
static TupleTypeRepr *create(ASTContext &C, ArrayRef<TypeRepr *> Elements,
535-
SourceRange Parens, SourceLoc Ellipsis);
540+
SourceRange Parens, SourceLoc Ellipsis,
541+
unsigned EllipsisIdx);
536542

537543
static bool classof(const TypeRepr *T) {
538544
return T->getKind() == TypeReprKind::Tuple;

include/swift/Serialization/ModuleFormat.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const uint16_t VERSION_MAJOR = 0;
5151
/// To ensure that two separate changes don't silently get merged into one
5252
/// in source control, you should also update the comment to briefly
5353
/// describe what change you made.
54-
const uint16_t VERSION_MINOR = 207; // Last change: @NSManaged on methods
54+
const uint16_t VERSION_MINOR = 208; // Last change: tuple elt has ellipsis
5555

5656
using DeclID = Fixnum<31>;
5757
using DeclIDField = BCFixed<31>;
@@ -995,14 +995,14 @@ namespace decls_block {
995995
TUPLE_PATTERN,
996996
TypeIDField, // type
997997
BCVBR<5>, // arity
998-
BCFixed<1>, // implicit?
999-
BCFixed<1> // has vararg?
998+
BCFixed<1> // implicit?
1000999
// The elements trail the record.
10011000
>;
10021001

10031002
using TuplePatternEltLayout = BCRecordLayout<
10041003
TUPLE_PATTERN_ELT,
10051004
IdentifierIDField, // label
1005+
BCFixed<1>, // has ellipsis?
10061006
DefaultArgumentField // default argument
10071007
// The element pattern trails the record.
10081008
>;

lib/AST/ASTDumper.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,6 @@ namespace {
222222
}
223223
void visitTuplePattern(TuplePattern *P) {
224224
printCommon(P, "pattern_tuple");
225-
if (P->hasVararg())
226-
OS << " hasVararg";
227225

228226
OS << " names=";
229227
interleave(P->getElements(),
@@ -236,6 +234,8 @@ namespace {
236234
for (auto &elt : P->getElements()) {
237235
OS << '\n';
238236
printRec(elt.getPattern());
237+
if (elt.hasEllipsis())
238+
OS << " ellipsis";
239239
if (elt.getInit()) {
240240
OS << '\n';
241241
printRec(elt.getInit()->getExpr());
@@ -1681,7 +1681,16 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
16811681
if (i) OS << ", ";
16821682
OS << E->getElementMapping()[i];
16831683
}
1684-
OS << "]\n";
1684+
OS << "]";
1685+
OS << " variadic_sources=[";
1686+
interleave(E->getVariadicArgs(),
1687+
[&](unsigned source) {
1688+
OS << source;
1689+
},
1690+
[&] { OS << ", "; });
1691+
OS << "]";
1692+
1693+
OS << "\n";
16851694
printRec(E->getSubExpr());
16861695
OS << ')';
16871696
}

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -465,9 +465,10 @@ void PrintAST::printPattern(const Pattern *pattern) {
465465
if (i != 0)
466466
Printer << ", ";
467467

468-
if (i == e - 1 && TP->hasVararg()) {
468+
if (Elt.hasEllipsis()) {
469469
printTypedPattern(cast<TypedPattern>(Elt.getPattern()),
470470
/*StripOuterSliceType=*/true);
471+
Printer << "...";
471472
} else {
472473
printPattern(Elt.getPattern());
473474
}
@@ -479,8 +480,6 @@ void PrintAST::printPattern(const Pattern *pattern) {
479480
}
480481
}
481482
}
482-
if (TP->hasVararg())
483-
Printer << "...";
484483
Printer << ")";
485484
break;
486485
}
@@ -1524,16 +1523,15 @@ void PrintAST::printFunctionParameters(AbstractFunctionDecl *AFD) {
15241523

15251524
printOneParameter(BodyTuple->getElement(i).getPattern(),
15261525
ArgNameIsAPIByDefault,
1527-
/*StripOuterSliceType=*/i == e - 1 &&
1528-
BodyTuple->hasVararg(),
1526+
BodyTuple->getElement(i).hasEllipsis(),
15291527
/*Curried=*/CurrPattern > 0);
1528+
if (BodyTuple->getElement(i).hasEllipsis())
1529+
Printer << "...";
15301530
if (Options.PrintDefaultParameterPlaceholder &&
15311531
BodyTuple->getElement(i).getDefaultArgKind() !=
15321532
DefaultArgumentKind::None)
15331533
Printer << " = default";
15341534
}
1535-
if (BodyTuple->hasVararg())
1536-
Printer << "...";
15371535
Printer << ")";
15381536
continue;
15391537
}
@@ -1731,12 +1729,11 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) {
17311729

17321730
printOneParameter(BodyTuple->getElement(i).getPattern(),
17331731
/*ArgNameIsAPIByDefault=*/false,
1734-
/*StripOuterSliceType=*/i == e - 1 &&
1735-
BodyTuple->hasVararg(),
1732+
BodyTuple->getElement(i).hasEllipsis(),
17361733
/*Curried=*/false);
1734+
if (BodyTuple->getElement(i).hasEllipsis())
1735+
Printer << "...";
17371736
}
1738-
if (BodyTuple->hasVararg())
1739-
Printer << "...";
17401737
} else {
17411738
auto *BodyParen = cast<ParenPattern>(IndicePat);
17421739
Printer << "(";

lib/AST/Decl.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3911,7 +3911,8 @@ bool FuncDecl::isUnaryOperator() const {
39113911
if (!argTuple)
39123912
return true;
39133913

3914-
return argTuple->getNumElements() == 1 && !argTuple->hasVararg();
3914+
return argTuple->getNumElements() == 1 &&
3915+
!argTuple->getElement(0).hasEllipsis();
39153916
}
39163917

39173918
bool FuncDecl::isBinaryOperator() const {
@@ -3926,7 +3927,8 @@ bool FuncDecl::isBinaryOperator() const {
39263927
return false;
39273928

39283929
return argTuple->getNumElements() == 2
3929-
|| (argTuple->getNumElements() == 1 && argTuple->hasVararg());
3930+
|| (argTuple->getNumElements() == 1 &&
3931+
argTuple->getElement(0).hasEllipsis());
39303932
}
39313933

39323934
bool FuncDecl::isOverridingDecl(const FuncDecl *Method) const {
@@ -3980,7 +3982,8 @@ bool ConstructorDecl::isObjCZeroParameterWithLongSelector() const {
39803982
const Pattern *paramPattern = getBodyParamPatterns()[1];
39813983
Type paramType;
39823984
if (auto tuplePattern = dyn_cast<TuplePattern>(paramPattern)) {
3983-
if (tuplePattern->getNumElements() != 1 || tuplePattern->hasVararg())
3985+
if (tuplePattern->getNumElements() != 1 ||
3986+
tuplePattern->getElement(0).hasEllipsis())
39843987
return false;
39853988

39863989
paramType = tuplePattern->getElement(0).getPattern()->getType();

0 commit comments

Comments
 (0)