Skip to content

Commit c6a266e

Browse files
authored
Merge pull request swiftlang#29735 from owenv/multiple-varargs
[SE-0284] Allow Multiple Variadic Parameters in Functions, Subscripts, and Initializers
2 parents ea5604e + 9708247 commit c6a266e

File tree

8 files changed

+257
-22
lines changed

8 files changed

+257
-22
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -882,8 +882,6 @@ ERROR(expected_parameter_colon,PointsToFirstBadToken,
882882
"expected ':' following argument label and parameter name", ())
883883
ERROR(expected_assignment_instead_of_comparison_operator,none,
884884
"expected '=' instead of '==' to assign default value for parameter", ())
885-
ERROR(multiple_parameter_ellipsis,none,
886-
"only a single variadic parameter '...' is permitted", ())
887885
ERROR(parameter_vararg_default,none,
888886
"variadic parameter cannot have a default value", ())
889887
ERROR(parameter_specifier_as_attr_disallowed,none,
@@ -916,6 +914,8 @@ ERROR(initializer_as_typed_pattern,none,
916914

917915
ERROR(unlabeled_parameter_following_variadic_parameter,none,
918916
"a parameter following a variadic parameter requires a label", ())
917+
ERROR(closure_unlabeled_parameter_following_variadic_parameter,none,
918+
"no parameters may follow a variadic parameter in a closure", ())
919919

920920
ERROR(enum_element_empty_arglist,none,
921921
"enum element with associated values must have at least one "

lib/Parse/ParsePattern.cpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,6 @@ mapParsedParameters(Parser &parser,
574574
// Collect the elements of the tuple patterns for argument and body
575575
// parameters.
576576
SmallVector<ParamDecl*, 4> elements;
577-
SourceLoc ellipsisLoc;
578577

579578
for (auto &param : params) {
580579
// Whether the provided name is API by default depends on the parameter
@@ -625,27 +624,26 @@ mapParsedParameters(Parser &parser,
625624
}
626625

627626
// Warn when an unlabeled parameter follows a variadic parameter
628-
if (ellipsisLoc.isValid() && elements.back()->isVariadic() &&
629-
param.FirstName.empty()) {
630-
parser.diagnose(param.FirstNameLoc,
631-
diag::unlabeled_parameter_following_variadic_parameter);
627+
if (!elements.empty() && elements.back()->isVariadic() && argName.empty()) {
628+
// Closure parameters can't have external labels, so use a more specific
629+
// diagnostic.
630+
if (paramContext == Parser::ParameterContextKind::Closure)
631+
parser.diagnose(
632+
param.FirstNameLoc,
633+
diag::closure_unlabeled_parameter_following_variadic_parameter);
634+
else
635+
parser.diagnose(param.FirstNameLoc,
636+
diag::unlabeled_parameter_following_variadic_parameter);
632637
}
633-
634-
// If this parameter had an ellipsis, check whether it's the last parameter.
635-
if (param.EllipsisLoc.isValid()) {
636-
if (ellipsisLoc.isValid()) {
637-
parser.diagnose(param.EllipsisLoc, diag::multiple_parameter_ellipsis)
638-
.highlight(ellipsisLoc)
639-
.fixItRemove(param.EllipsisLoc);
640638

641-
param.EllipsisLoc = SourceLoc();
642-
} else if (!result->getTypeRepr()) {
639+
// If this parameter had an ellipsis, check it has a TypeRepr.
640+
if (param.EllipsisLoc.isValid()) {
641+
if (!result->getTypeRepr()) {
643642
parser.diagnose(param.EllipsisLoc, diag::untyped_pattern_ellipsis)
644643
.highlight(result->getSourceRange());
645644

646645
param.EllipsisLoc = SourceLoc();
647646
} else {
648-
ellipsisLoc = param.EllipsisLoc;
649647
result->setVariadic();
650648
}
651649
}

test/Constraints/argument_matching.swift

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,93 @@ variadics6(x: 1, 2, 3) // expected-error{{missing argument for parameter 'z' in
305305
variadics6(x: 1) // expected-error{{missing argument for parameter 'z' in call}}
306306
variadics6() // expected-error{{missing argument for parameter 'z' in call}}
307307

308+
func variadics7(_ x: Int..., y: Int...) { }
309+
310+
// Using multiple variadics (in order, complete)
311+
variadics7(1, y: 2)
312+
variadics7(1, 2, 3, y: 4, 5, 6)
313+
variadics7(1, 2, y: 2)
314+
variadics7(1, y: 2, 1)
315+
316+
// multiple variadics, in order, some missing
317+
variadics7(y: 1)
318+
variadics7(1)
319+
variadics7(y: 4, 5, 6)
320+
variadics7(1, 2, 3)
321+
322+
func variadics8(x: Int..., y: Int...) { }
323+
324+
// multiple variadics, out of order
325+
variadics8(y: 1, x: 2) // expected-error {{argument 'x' must precede argument 'y'}} {{12-12=x: 2, }} {{16-22=}}
326+
variadics8(y: 1, 2, 3, x: 4) // expected-error {{argument 'x' must precede argument 'y'}} {{12-12=x: 4, }} {{22-28=}}
327+
variadics8(y: 1, x: 2, 3, 4) // expected-error {{argument 'x' must precede argument 'y'}} {{12-12=x: 2, 3, 4, }} {{16-28=}}
328+
variadics8(y: 1, 2, 3, x: 4, 5, 6) // expected-error {{argument 'x' must precede argument 'y'}} {{12-12=x: 4, 5, 6, }} {{22-34=}}
329+
330+
func variadics9(_ a: Int..., b: Int, _ c: Int...) { } // expected-note {{'variadics9(_:b:_:)' declared here}}
331+
332+
// multiple split variadics, in order, complete
333+
variadics9(1, b: 2, 3)
334+
variadics9(1, 2, 3, b: 2, 3)
335+
variadics9(1, b: 2, 3, 2, 1)
336+
variadics9(1, 2, 3, b: 2, 3, 2, 1)
337+
338+
// multiple split variadics, in order, some missing
339+
variadics9(b: 2, 3)
340+
variadics9(1, b: 2)
341+
variadics9(1, 2, b: 2)
342+
variadics9(b: 2, 3, 2, 1)
343+
344+
// multiple split variadics, required missing
345+
variadics9(1) // expected-error {{missing argument for parameter 'b' in call}}
346+
347+
func variadics10(_ a: Int..., b: Int = 2, _ c: Int...) { }
348+
349+
// multiple unlabeled variadics split by defaulted param, in order, complete
350+
variadics10(1, b: 2, 3)
351+
variadics10(1, 2, 3, b: 2, 3)
352+
variadics10(1, b: 2, 3, 2, 1)
353+
variadics10(1, 2, 3, b: 2, 3, 2, 1)
354+
355+
// multiple unlabeled variadics split by defaulted param, in order, some missing
356+
variadics10(1, 2, 3)
357+
variadics10(1, 2, 3, b: 3)
358+
variadics10(b: 3)
359+
360+
func variadics11(_ a: Int..., b: Bool = false, _ c: String...) { }
361+
362+
variadics11(1, 2, 3, b: true, "hello", "world")
363+
variadics11(b: true, "hello", "world")
364+
variadics11(1, 2, 3, b: true)
365+
variadics11(b: true)
366+
variadics11()
367+
variadics11(1, 2, 3, "hello", "world") // expected-error 2 {{cannot convert value of type 'String' to expected argument type 'Int'}}
368+
369+
func variadics12(a: Int..., b: Int, c: Int...) { }
370+
371+
variadics12(a: 1, 2, 3, b: 4, c: 5, 6, 7)
372+
variadics12(b: 4, c: 5, 6, 7)
373+
variadics12(a: 1, 2, 3, b: 4)
374+
375+
variadics12(c: 5, 6, 7, b: 4, a: 1, 2, 3) // expected-error {{incorrect argument labels in call (have 'c:_:_:b:a:_:_:', expected 'a:b:c:')}} {{13-14=a}} {{19-19=b: }} {{22-22=c: }} {{25-28=}} {{31-34=}}
376+
377+
378+
// Edge cases involving multiple trailing closures and forward matching.
379+
func variadics13(a: Int..., b: (()->Void)...) {}
380+
381+
variadics13()
382+
variadics13(a: 1, 2, 3) {} _: {} _: {}
383+
variadics13() {} _: {} _: {}
384+
variadics13(a: 1, 2, 3)
385+
variadics13(a: 1, 2, 3) {}
386+
387+
func variadics14(a: (()->Void)..., b: (()->Void)...) {} // expected-note {{'variadics14(a:b:)' declared here}}
388+
389+
variadics14(a: {}, {}, b: {}, {})
390+
variadics14(a: {}, {}) {} _: {}
391+
variadics14 {} _: {} b: {} _: {}
392+
variadics14 {} b: {}
393+
variadics14 {} // expected-warning {{backward matching of the unlabeled trailing closure is deprecated; label the argument with 'b' to suppress this warning}}
394+
308395
func outOfOrder(_ a : Int, b: Int) {
309396
outOfOrder(b: 42, 52) // expected-error {{unnamed argument #2 must precede argument 'b'}} {{14-14=52, }} {{19-23=}}
310397
}
@@ -1336,6 +1423,26 @@ d = sub2[d] // expected-error{{missing argument label 'd:' in subscript}} {{10-1
13361423
d = sub2[d: d]
13371424
d = sub2[f: d] // expected-error{{incorrect argument label in subscript (have 'f:', expected 'd:')}} {{10-11=d}}
13381425

1426+
struct Sub3 {
1427+
subscript (a: Int..., b b: Int...) -> Int { 42 }
1428+
}
1429+
1430+
let sub3 = Sub3()
1431+
_ = sub3[1, 2, 3, b: 4, 5, 6]
1432+
_ = sub3[b: 4, 5, 6]
1433+
_ = sub3[1, 2, 3]
1434+
_ = sub3[1, c: 4] // expected-error {{incorrect argument label in subscript (have '_:c:', expected '_:b:')}}
1435+
1436+
struct Sub4 {
1437+
subscript (a: Int..., b b: Int = 0, c: Int...) -> Int { 42 }
1438+
}
1439+
1440+
let sub4 = Sub4()
1441+
_ = sub4[1, 2, 3, b: 2, 1, 2, 3]
1442+
_ = sub4[1, 2, 3, b: 2]
1443+
_ = sub4[1, 2, 3]
1444+
_ = sub4[]
1445+
13391446
// -------------------------------------------
13401447
// Closures
13411448
// -------------------------------------------
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
3+
// REQUIRES: executable_test
4+
5+
func vf(x: Int..., y: Int...) {
6+
print(x, y)
7+
}
8+
9+
vf(x: 1, 2, 3, y: 4, 5, 6)
10+
// CHECK: [1, 2, 3] [4, 5, 6]
11+
vf(y: 1, 2)
12+
// CHECK: [] [1, 2]
13+
vf(x: 3, 4)
14+
// CHECK: [3, 4] []
15+
16+
func vf2(_ x: Int..., y: Int, _ z: Int...) {
17+
print(x, y, z)
18+
}
19+
20+
vf2(1, 2, 3, y: 4, 5, 6, 7)
21+
// CHECK: [1, 2, 3] 4 [5, 6, 7]
22+
vf2(y: 4, 5, 6, 7)
23+
// CHECK: [] 4 [5, 6, 7]
24+
vf2(1, 2, 3, y: 4)
25+
// CHECK: [1, 2, 3] 4 []
26+
vf2(y: 4)
27+
// CHECK: [] 4 []
28+
29+
func vf3(_ x: Int..., y: Int = 42, _ z: Int...) {
30+
print(x, y, z)
31+
}
32+
33+
vf3(1, 2, 3, y: 4, 5, 6, 7)
34+
// CHECK: [1, 2, 3] 4 [5, 6, 7]
35+
vf3(y: 4, 5, 6, 7)
36+
// CHECK: [] 4 [5, 6, 7]
37+
vf3(1, 2, 3, y: 4)
38+
// CHECK: [1, 2, 3] 4 []
39+
vf3(y: 4)
40+
// CHECK: [] 4 []
41+
42+
vf3()
43+
// CHECK: [] 42 []
44+
vf3(1, 2, 3)
45+
// CHECK: [1, 2, 3] 42 []
46+
47+
func foo(a: Int..., b: Int, c: Int..., d: Int) {
48+
print("one")
49+
}
50+
51+
func foo(a: [Int], b: Int, c: [Int], d: Int) {
52+
print("two")
53+
}
54+
55+
func foo(a: Int..., b: Int, c: [Int], d: Int) {
56+
print("three")
57+
}
58+
59+
foo(a: 1, 2, 3, b: 4, c: 5, 6, 7, d: 8)
60+
// CHECK: one
61+
foo(a: [1, 2, 3], b: 4, c: [5, 6, 7], d: 8)
62+
// CHECK: two
63+
foo(a: 1, 2, 3, b: 4, c: [5, 6, 7], d: 8)
64+
// CHECK: three
65+
66+
struct Baz {
67+
init(a: Int..., b: Int...) {
68+
print(a, b)
69+
}
70+
71+
init(_ a: Int..., b: String, _ c: Int...) {
72+
print(a, b, c)
73+
}
74+
75+
subscript(a: Int..., b b: Int...) -> [Int] { a + b }
76+
}
77+
78+
let baz1 = Baz(a: 1, 2, 3, b: 4, 5, 6)
79+
// CHECK: [1, 2, 3] [4, 5, 6]
80+
81+
let baz2 = Baz(1, 2, 3, b: "hello, world!", 3, 2, 1)
82+
// CHECK: [1, 2, 3] hello, world! [3, 2, 1]
83+
84+
print(baz1[1, 2, b: 3, 4])
85+
// CHECK: [1, 2, 3, 4]

test/SILGen/arguments.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ func variadic_arg_3(_ y: Float..., x: Int) {}
8282
// CHECK-LABEL: sil hidden [ossa] @$ss14variadic_arg_3{{[_0-9a-zA-Z]*}}F
8383
// CHECK: bb0([[Y:%[0-9]+]] : $Array<Float>, [[X:%[0-9]+]] : $Int):
8484

85+
func variadic_arg_4(_ y: Float..., x: Int...) {}
86+
// CHECK-LABEL: sil hidden [ossa] @$ss14variadic_arg_4{{[_0-9a-zA-Z]*}}F
87+
// CHECK: bb0([[Y:%[0-9]+]] : $Array<Float>, [[X:%[0-9]+]] : $Array<Int>):
88+
89+
func variadic_arg_5(a: Int, b: Float..., c: Int, d: Int...) {}
90+
// CHECK-LABEL: sil hidden [ossa] @$ss14variadic_arg_5{{[_0-9a-zA-Z]*}}F
91+
// CHECK: bb0([[A:%[0-9]+]] : $Int, [[B:%[0-9]+]] : $Array<Float>, [[C:%[0-9]+]] : $Int, [[D:%[0-9]+]] : $Array<Int>):
92+
8593
variadic_arg_3(x: i)
8694
variadic_arg_3(f, x: i)
8795
variadic_arg_3(f, f, f, x: i)

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,15 @@ class C <MemberDeclBlock>{<MemberDeclListItem><FunctionDecl>
102102
@objc </Attribute><DeclModifier>private </DeclModifier>init<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>)</ParameterClause></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl>
103103
init!<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl>
104104
init?<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl><DeclModifier>
105-
public </DeclModifier>init<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause>throws <CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><DeinitializerDecl><Attribute>
105+
public </DeclModifier>init<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause>throws <CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl>
106+
init<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>..., </FunctionParameter><FunctionParameter>b: <SimpleTypeIdentifier>Double</SimpleTypeIdentifier>...</FunctionParameter>) </ParameterClause><CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><DeinitializerDecl><Attribute>
106107

107108
@objc </Attribute>deinit <CodeBlock>{}</CodeBlock></DeinitializerDecl></MemberDeclListItem><MemberDeclListItem><DeinitializerDecl><DeclModifier>
108109
private </DeclModifier>deinit <CodeBlock>{}</CodeBlock></DeinitializerDecl></MemberDeclListItem><MemberDeclListItem><SubscriptDecl><DeclModifier>
109110

110111
internal </DeclModifier>subscript<ParameterClause>(<FunctionParameter>x: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause><AccessorBlock>{ <AccessorDecl>get <CodeBlock>{} </CodeBlock></AccessorDecl><AccessorDecl>set <CodeBlock>{} </CodeBlock></AccessorDecl>}</AccessorBlock></SubscriptDecl></MemberDeclListItem><MemberDeclListItem><SubscriptDecl>
111-
subscript<ParameterClause>() </ParameterClause><ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock></SubscriptDecl></MemberDeclListItem><MemberDeclListItem><VariableDecl>
112+
subscript<ParameterClause>() </ParameterClause><ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock></SubscriptDecl></MemberDeclListItem><MemberDeclListItem><SubscriptDecl>
113+
subscript<ParameterClause>(<FunctionParameter>x: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>..., </FunctionParameter><FunctionParameter>y y: <SimpleTypeIdentifier>String</SimpleTypeIdentifier>...</FunctionParameter>) </ParameterClause><ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock></SubscriptDecl></MemberDeclListItem><MemberDeclListItem><VariableDecl>
112114

113115
var <PatternBinding><IdentifierPattern>x</IdentifierPattern><TypeAnnotation>: <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></TypeAnnotation><CodeBlock>{<FunctionCallExpr><IdentifierExpr>
114116
address </IdentifierExpr><ClosureExpr>{ <FunctionCallExpr><IdentifierExpr>fatalError</IdentifierExpr>() </FunctionCallExpr>}</ClosureExpr></FunctionCallExpr><FunctionCallExpr><IdentifierExpr>
@@ -197,7 +199,8 @@ func foo<FunctionSignature><ParameterClause>(<FunctionParameter>_ _: <SimpleType
197199
d _: <SimpleTypeIdentifier>Int </SimpleTypeIdentifier><InitializerClause>= <SequenceExpr><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>2</IntegerLiteralExpr>: <IntegerLiteralExpr>3</IntegerLiteralExpr></TernaryExpr></SequenceExpr></InitializerClause>,</FunctionParameter><FunctionParameter><Attribute>
198200
@objc </Attribute>e: <SimpleTypeIdentifier>X </SimpleTypeIdentifier><InitializerClause>= <BooleanLiteralExpr>true</BooleanLiteralExpr></InitializerClause>,</FunctionParameter><FunctionParameter>
199201
f: <AttributedType>inout <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></AttributedType>,</FunctionParameter><FunctionParameter>
200-
g: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>...</FunctionParameter>) </ParameterClause>throws <ReturnClause>-> <DictionaryType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>: <SimpleTypeIdentifier>String</SimpleTypeIdentifier>] </DictionaryType></ReturnClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl>
202+
g: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>...,</FunctionParameter><FunctionParameter>
203+
h: <SimpleTypeIdentifier>Bool</SimpleTypeIdentifier>...</FunctionParameter>) </ParameterClause>throws <ReturnClause>-> <DictionaryType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>: <SimpleTypeIdentifier>String</SimpleTypeIdentifier>] </DictionaryType></ReturnClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl>
201204

202205
func foo<FunctionSignature><ParameterClause>(<FunctionParameter>_ a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause>throws <ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl>
203206
func foo<FunctionSignature><ParameterClause>( <FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause>rethrows <ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><StructDecl>

test/Syntax/round_trip_parse_gen.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,14 @@ class C {
103103
init!(a: Int) {}
104104
init?(a: Int) {}
105105
public init(a: Int) throws {}
106+
init(a: Int..., b: Double...) {}
106107

107108
@objc deinit {}
108109
private deinit {}
109110

110111
internal subscript(x: Int) -> Int { get {} set {} }
111112
subscript() -> Int { return 1 }
113+
subscript(x: Int..., y y: String...) -> Int { return 1 }
112114

113115
var x: Int {
114116
address { fatalError() }
@@ -197,7 +199,8 @@ func foo(_ _: Int,
197199
d _: Int = true ? 2: 3,
198200
@objc e: X = true,
199201
f: inout Int,
200-
g: Int...) throws -> [Int: String] {}
202+
g: Int...,
203+
h: Bool...) throws -> [Int: String] {}
201204

202205
func foo(_ a: Int) throws -> Int {}
203206
func foo( a: Int) rethrows -> Int {}

test/decl/func/vararg.swift

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,38 @@ func invalidVariadic(_ e: NonExistentType) { // expected-error {{cannot find typ
2727
{ (e: ExtraCrispy...) in }() // expected-error {{cannot find type 'ExtraCrispy' in scope}}
2828
}
2929

30-
func twoVariadics(_ a: Int..., b: Int...) { } // expected-error{{only a single variadic parameter '...' is permitted}} {{38-41=}}
30+
func twoVariadics(_ a: Int..., b: Int...) { }
31+
func unlabeledFollowingVariadic(_ a: Int..., _ b: Int) { } // expected-error {{a parameter following a variadic parameter requires a label}}
32+
func unlabeledVariadicFollowingVariadic(_ a: Int..., _ b: Int...) { } // expected-error {{a parameter following a variadic parameter requires a label}}
33+
func unlabeledFollowingTwoVariadics(_ a: Int..., b: Int..., _ c: Int) { } // expected-error {{a parameter following a variadic parameter requires a label}}
34+
func splitVariadics(_ a: Int..., b: Int, _ c: String...) { }
35+
func splitByDefaultArgVariadics(_ a: Int..., b: Int = 0, _ c: String...) { }
36+
37+
struct HasSubscripts {
38+
subscript(a: Int...) -> Void { () }
39+
subscript(a: Int..., b b: Int...) -> Void { () }
40+
subscript(a: Int..., b: Int...) -> Void { () } // expected-error {{a parameter following a variadic parameter requires a label}}
41+
subscript(a: Int..., b: Int) -> Void { () } // expected-error {{a parameter following a variadic parameter requires a label}}
42+
subscript(a: Int..., b b: Int..., c c: Int) -> Void { () }
43+
subscript(a: Int..., b b: Int..., c: Int) -> Void { () } // expected-error {{a parameter following a variadic parameter requires a label}}
44+
subscript(a: Int..., c c: Int = 0, b: Int...) -> Void { () }
45+
subscript(a: Int..., b: String = "hello, world!") -> Bool { false } // expected-error {{a parameter following a variadic parameter requires a label}}
46+
}
47+
48+
struct HasInitializers {
49+
init(a: Int...) {}
50+
init(a: Int..., b: Int...) {}
51+
init(a: Int..., _ b: Int...) {} // expected-error {{a parameter following a variadic parameter requires a label}}
52+
init(a: Int..., c: Int = 0, _ b: Int...) {}
53+
}
54+
55+
let closure = {(x: Int..., y: Int...) in } // expected-error {{no parameters may follow a variadic parameter in a closure}}
56+
let closure2 = {(x: Int..., y: Int) in } // expected-error {{no parameters may follow a variadic parameter in a closure}}
57+
let closure3 = {(x: Int..., y: Int, z: Int...) in } // expected-error {{no parameters may follow a variadic parameter in a closure}}
58+
let closure4 = {(x: Int...) in }
59+
let closure5 = {(x: Int, y: Int...) in }
60+
let closure6 = {(x: Int..., y z: Int) in } // expected-error {{closure cannot have keyword arguments}}
61+
// expected-error@-1 {{no parameters may follow a variadic parameter in a closure}}
3162

3263
// rdar://22056861
3364
func f5(_ list: Any..., end: String = "") {}

0 commit comments

Comments
 (0)