Skip to content

[SE-0284] Allow Multiple Variadic Parameters in Functions, Subscripts, and Initializers #29735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -882,8 +882,6 @@ ERROR(expected_parameter_colon,PointsToFirstBadToken,
"expected ':' following argument label and parameter name", ())
ERROR(expected_assignment_instead_of_comparison_operator,none,
"expected '=' instead of '==' to assign default value for parameter", ())
ERROR(multiple_parameter_ellipsis,none,
"only a single variadic parameter '...' is permitted", ())
ERROR(parameter_vararg_default,none,
"variadic parameter cannot have a default value", ())
ERROR(parameter_specifier_as_attr_disallowed,none,
Expand Down Expand Up @@ -916,6 +914,8 @@ ERROR(initializer_as_typed_pattern,none,

ERROR(unlabeled_parameter_following_variadic_parameter,none,
"a parameter following a variadic parameter requires a label", ())
ERROR(closure_unlabeled_parameter_following_variadic_parameter,none,
"no parameters may follow a variadic parameter in a closure", ())

ERROR(enum_element_empty_arglist,none,
"enum element with associated values must have at least one "
Expand Down
28 changes: 13 additions & 15 deletions lib/Parse/ParsePattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,6 @@ mapParsedParameters(Parser &parser,
// Collect the elements of the tuple patterns for argument and body
// parameters.
SmallVector<ParamDecl*, 4> elements;
SourceLoc ellipsisLoc;

for (auto &param : params) {
// Whether the provided name is API by default depends on the parameter
Expand Down Expand Up @@ -623,27 +622,26 @@ mapParsedParameters(Parser &parser,
}

// Warn when an unlabeled parameter follows a variadic parameter
if (ellipsisLoc.isValid() && elements.back()->isVariadic() &&
param.FirstName.empty()) {
parser.diagnose(param.FirstNameLoc,
diag::unlabeled_parameter_following_variadic_parameter);
if (!elements.empty() && elements.back()->isVariadic() && argName.empty()) {
// Closure parameters can't have external labels, so use a more specific
// diagnostic.
if (paramContext == Parser::ParameterContextKind::Closure)
parser.diagnose(
param.FirstNameLoc,
diag::closure_unlabeled_parameter_following_variadic_parameter);
else
parser.diagnose(param.FirstNameLoc,
diag::unlabeled_parameter_following_variadic_parameter);
}

// If this parameter had an ellipsis, check whether it's the last parameter.
if (param.EllipsisLoc.isValid()) {
if (ellipsisLoc.isValid()) {
parser.diagnose(param.EllipsisLoc, diag::multiple_parameter_ellipsis)
.highlight(ellipsisLoc)
.fixItRemove(param.EllipsisLoc);

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

param.EllipsisLoc = SourceLoc();
} else {
ellipsisLoc = param.EllipsisLoc;
result->setVariadic();
}
}
Expand Down
107 changes: 107 additions & 0 deletions test/Constraints/argument_matching.swift
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,93 @@ variadics6(x: 1, 2, 3) // expected-error{{missing argument for parameter 'z' in
variadics6(x: 1) // expected-error{{missing argument for parameter 'z' in call}}
variadics6() // expected-error{{missing argument for parameter 'z' in call}}

func variadics7(_ x: Int..., y: Int...) { }

// Using multiple variadics (in order, complete)
variadics7(1, y: 2)
variadics7(1, 2, 3, y: 4, 5, 6)
variadics7(1, 2, y: 2)
variadics7(1, y: 2, 1)

// multiple variadics, in order, some missing
variadics7(y: 1)
variadics7(1)
variadics7(y: 4, 5, 6)
variadics7(1, 2, 3)

func variadics8(x: Int..., y: Int...) { }

// multiple variadics, out of order
variadics8(y: 1, x: 2) // expected-error {{argument 'x' must precede argument 'y'}} {{12-12=x: 2, }} {{16-22=}}
variadics8(y: 1, 2, 3, x: 4) // expected-error {{argument 'x' must precede argument 'y'}} {{12-12=x: 4, }} {{22-28=}}
variadics8(y: 1, x: 2, 3, 4) // expected-error {{argument 'x' must precede argument 'y'}} {{12-12=x: 2, 3, 4, }} {{16-28=}}
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=}}

func variadics9(_ a: Int..., b: Int, _ c: Int...) { } // expected-note {{'variadics9(_:b:_:)' declared here}}

// multiple split variadics, in order, complete
variadics9(1, b: 2, 3)
variadics9(1, 2, 3, b: 2, 3)
variadics9(1, b: 2, 3, 2, 1)
variadics9(1, 2, 3, b: 2, 3, 2, 1)

// multiple split variadics, in order, some missing
variadics9(b: 2, 3)
variadics9(1, b: 2)
variadics9(1, 2, b: 2)
variadics9(b: 2, 3, 2, 1)

// multiple split variadics, required missing
variadics9(1) // expected-error {{missing argument for parameter 'b' in call}}

func variadics10(_ a: Int..., b: Int = 2, _ c: Int...) { }

// multiple unlabeled variadics split by defaulted param, in order, complete
variadics10(1, b: 2, 3)
variadics10(1, 2, 3, b: 2, 3)
variadics10(1, b: 2, 3, 2, 1)
variadics10(1, 2, 3, b: 2, 3, 2, 1)

// multiple unlabeled variadics split by defaulted param, in order, some missing
variadics10(1, 2, 3)
variadics10(1, 2, 3, b: 3)
variadics10(b: 3)

func variadics11(_ a: Int..., b: Bool = false, _ c: String...) { }

variadics11(1, 2, 3, b: true, "hello", "world")
variadics11(b: true, "hello", "world")
variadics11(1, 2, 3, b: true)
variadics11(b: true)
variadics11()
variadics11(1, 2, 3, "hello", "world") // expected-error 2 {{cannot convert value of type 'String' to expected argument type 'Int'}}

func variadics12(a: Int..., b: Int, c: Int...) { }

variadics12(a: 1, 2, 3, b: 4, c: 5, 6, 7)
variadics12(b: 4, c: 5, 6, 7)
variadics12(a: 1, 2, 3, b: 4)

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=}}


// Edge cases involving multiple trailing closures and forward matching.
func variadics13(a: Int..., b: (()->Void)...) {}

variadics13()
variadics13(a: 1, 2, 3) {} _: {} _: {}
variadics13() {} _: {} _: {}
variadics13(a: 1, 2, 3)
variadics13(a: 1, 2, 3) {}

func variadics14(a: (()->Void)..., b: (()->Void)...) {} // expected-note {{'variadics14(a:b:)' declared here}}

variadics14(a: {}, {}, b: {}, {})
variadics14(a: {}, {}) {} _: {}
variadics14 {} _: {} b: {} _: {}
variadics14 {} b: {}
variadics14 {} // expected-warning {{backward matching of the unlabeled trailing closure is deprecated; label the argument with 'b' to suppress this warning}}

func outOfOrder(_ a : Int, b: Int) {
outOfOrder(b: 42, 52) // expected-error {{unnamed argument #2 must precede argument 'b'}} {{14-14=52, }} {{19-23=}}
}
Expand Down Expand Up @@ -1336,6 +1423,26 @@ d = sub2[d] // expected-error{{missing argument label 'd:' in subscript}} {{10-1
d = sub2[d: d]
d = sub2[f: d] // expected-error{{incorrect argument label in subscript (have 'f:', expected 'd:')}} {{10-11=d}}

struct Sub3 {
subscript (a: Int..., b b: Int...) -> Int { 42 }
}

let sub3 = Sub3()
_ = sub3[1, 2, 3, b: 4, 5, 6]
_ = sub3[b: 4, 5, 6]
_ = sub3[1, 2, 3]
_ = sub3[1, c: 4] // expected-error {{incorrect argument label in subscript (have '_:c:', expected '_:b:')}}

struct Sub4 {
subscript (a: Int..., b b: Int = 0, c: Int...) -> Int { 42 }
}

let sub4 = Sub4()
_ = sub4[1, 2, 3, b: 2, 1, 2, 3]
_ = sub4[1, 2, 3, b: 2]
_ = sub4[1, 2, 3]
_ = sub4[]

// -------------------------------------------
// Closures
// -------------------------------------------
Expand Down
85 changes: 85 additions & 0 deletions test/Interpreter/multiple_varargs.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// RUN: %target-run-simple-swift | %FileCheck %s

// REQUIRES: executable_test

func vf(x: Int..., y: Int...) {
print(x, y)
}

vf(x: 1, 2, 3, y: 4, 5, 6)
// CHECK: [1, 2, 3] [4, 5, 6]
vf(y: 1, 2)
// CHECK: [] [1, 2]
vf(x: 3, 4)
// CHECK: [3, 4] []

func vf2(_ x: Int..., y: Int, _ z: Int...) {
print(x, y, z)
}

vf2(1, 2, 3, y: 4, 5, 6, 7)
// CHECK: [1, 2, 3] 4 [5, 6, 7]
vf2(y: 4, 5, 6, 7)
// CHECK: [] 4 [5, 6, 7]
vf2(1, 2, 3, y: 4)
// CHECK: [1, 2, 3] 4 []
vf2(y: 4)
// CHECK: [] 4 []

func vf3(_ x: Int..., y: Int = 42, _ z: Int...) {
print(x, y, z)
}

vf3(1, 2, 3, y: 4, 5, 6, 7)
// CHECK: [1, 2, 3] 4 [5, 6, 7]
vf3(y: 4, 5, 6, 7)
// CHECK: [] 4 [5, 6, 7]
vf3(1, 2, 3, y: 4)
// CHECK: [1, 2, 3] 4 []
vf3(y: 4)
// CHECK: [] 4 []

vf3()
// CHECK: [] 42 []
vf3(1, 2, 3)
// CHECK: [1, 2, 3] 42 []

func foo(a: Int..., b: Int, c: Int..., d: Int) {
print("one")
}

func foo(a: [Int], b: Int, c: [Int], d: Int) {
print("two")
}

func foo(a: Int..., b: Int, c: [Int], d: Int) {
print("three")
}

foo(a: 1, 2, 3, b: 4, c: 5, 6, 7, d: 8)
// CHECK: one
foo(a: [1, 2, 3], b: 4, c: [5, 6, 7], d: 8)
// CHECK: two
foo(a: 1, 2, 3, b: 4, c: [5, 6, 7], d: 8)
// CHECK: three

struct Baz {
init(a: Int..., b: Int...) {
print(a, b)
}

init(_ a: Int..., b: String, _ c: Int...) {
print(a, b, c)
}

subscript(a: Int..., b b: Int...) -> [Int] { a + b }
}

let baz1 = Baz(a: 1, 2, 3, b: 4, 5, 6)
// CHECK: [1, 2, 3] [4, 5, 6]

let baz2 = Baz(1, 2, 3, b: "hello, world!", 3, 2, 1)
// CHECK: [1, 2, 3] hello, world! [3, 2, 1]

print(baz1[1, 2, b: 3, 4])
// CHECK: [1, 2, 3, 4]
8 changes: 8 additions & 0 deletions test/SILGen/arguments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ func variadic_arg_3(_ y: Float..., x: Int) {}
// CHECK-LABEL: sil hidden [ossa] @$ss14variadic_arg_3{{[_0-9a-zA-Z]*}}F
// CHECK: bb0([[Y:%[0-9]+]] : $Array<Float>, [[X:%[0-9]+]] : $Int):

func variadic_arg_4(_ y: Float..., x: Int...) {}
// CHECK-LABEL: sil hidden [ossa] @$ss14variadic_arg_4{{[_0-9a-zA-Z]*}}F
// CHECK: bb0([[Y:%[0-9]+]] : $Array<Float>, [[X:%[0-9]+]] : $Array<Int>):

func variadic_arg_5(a: Int, b: Float..., c: Int, d: Int...) {}
// CHECK-LABEL: sil hidden [ossa] @$ss14variadic_arg_5{{[_0-9a-zA-Z]*}}F
// CHECK: bb0([[A:%[0-9]+]] : $Int, [[B:%[0-9]+]] : $Array<Float>, [[C:%[0-9]+]] : $Int, [[D:%[0-9]+]] : $Array<Int>):

variadic_arg_3(x: i)
variadic_arg_3(f, x: i)
variadic_arg_3(f, f, f, x: i)
Expand Down
9 changes: 6 additions & 3 deletions test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,15 @@ class C <MemberDeclBlock>{<MemberDeclListItem><FunctionDecl>
@objc </Attribute><DeclModifier>private </DeclModifier>init<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>)</ParameterClause></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl>
init!<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl>
init?<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl><DeclModifier>
public </DeclModifier>init<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause>throws <CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><DeinitializerDecl><Attribute>
public </DeclModifier>init<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause>throws <CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl>
init<ParameterClause>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>..., </FunctionParameter><FunctionParameter>b: <SimpleTypeIdentifier>Double</SimpleTypeIdentifier>...</FunctionParameter>) </ParameterClause><CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><DeinitializerDecl><Attribute>

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

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>
subscript<ParameterClause>() </ParameterClause><ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock></SubscriptDecl></MemberDeclListItem><MemberDeclListItem><VariableDecl>
subscript<ParameterClause>() </ParameterClause><ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock></SubscriptDecl></MemberDeclListItem><MemberDeclListItem><SubscriptDecl>
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>

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

func foo<FunctionSignature><ParameterClause>(<FunctionParameter>_ a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause>throws <ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl>
func foo<FunctionSignature><ParameterClause>( <FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause>rethrows <ReturnClause>-> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></ReturnClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><StructDecl>
Expand Down
5 changes: 4 additions & 1 deletion test/Syntax/round_trip_parse_gen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,14 @@ class C {
init!(a: Int) {}
init?(a: Int) {}
public init(a: Int) throws {}
init(a: Int..., b: Double...) {}

@objc deinit {}
private deinit {}

internal subscript(x: Int) -> Int { get {} set {} }
subscript() -> Int { return 1 }
subscript(x: Int..., y y: String...) -> Int { return 1 }

var x: Int {
address { fatalError() }
Expand Down Expand Up @@ -197,7 +199,8 @@ func foo(_ _: Int,
d _: Int = true ? 2: 3,
@objc e: X = true,
f: inout Int,
g: Int...) throws -> [Int: String] {}
g: Int...,
h: Bool...) throws -> [Int: String] {}

func foo(_ a: Int) throws -> Int {}
func foo( a: Int) rethrows -> Int {}
Expand Down
33 changes: 32 additions & 1 deletion test/decl/func/vararg.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,38 @@ func invalidVariadic(_ e: NonExistentType) { // expected-error {{cannot find typ
{ (e: ExtraCrispy...) in }() // expected-error {{cannot find type 'ExtraCrispy' in scope}}
}

func twoVariadics(_ a: Int..., b: Int...) { } // expected-error{{only a single variadic parameter '...' is permitted}} {{38-41=}}
func twoVariadics(_ a: Int..., b: Int...) { }
func unlabeledFollowingVariadic(_ a: Int..., _ b: Int) { } // expected-error {{a parameter following a variadic parameter requires a label}}
func unlabeledVariadicFollowingVariadic(_ a: Int..., _ b: Int...) { } // expected-error {{a parameter following a variadic parameter requires a label}}
func unlabeledFollowingTwoVariadics(_ a: Int..., b: Int..., _ c: Int) { } // expected-error {{a parameter following a variadic parameter requires a label}}
func splitVariadics(_ a: Int..., b: Int, _ c: String...) { }
func splitByDefaultArgVariadics(_ a: Int..., b: Int = 0, _ c: String...) { }

struct HasSubscripts {
subscript(a: Int...) -> Void { () }
subscript(a: Int..., b b: Int...) -> Void { () }
subscript(a: Int..., b: Int...) -> Void { () } // expected-error {{a parameter following a variadic parameter requires a label}}
subscript(a: Int..., b: Int) -> Void { () } // expected-error {{a parameter following a variadic parameter requires a label}}
subscript(a: Int..., b b: Int..., c c: Int) -> Void { () }
subscript(a: Int..., b b: Int..., c: Int) -> Void { () } // expected-error {{a parameter following a variadic parameter requires a label}}
subscript(a: Int..., c c: Int = 0, b: Int...) -> Void { () }
subscript(a: Int..., b: String = "hello, world!") -> Bool { false } // expected-error {{a parameter following a variadic parameter requires a label}}
}

struct HasInitializers {
init(a: Int...) {}
init(a: Int..., b: Int...) {}
init(a: Int..., _ b: Int...) {} // expected-error {{a parameter following a variadic parameter requires a label}}
init(a: Int..., c: Int = 0, _ b: Int...) {}
}

let closure = {(x: Int..., y: Int...) in } // expected-error {{no parameters may follow a variadic parameter in a closure}}
let closure2 = {(x: Int..., y: Int) in } // expected-error {{no parameters may follow a variadic parameter in a closure}}
let closure3 = {(x: Int..., y: Int, z: Int...) in } // expected-error {{no parameters may follow a variadic parameter in a closure}}
let closure4 = {(x: Int...) in }
let closure5 = {(x: Int, y: Int...) in }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess {(x: Int..., y z: Int) in } is still diagnosed as error: closure cannot have keyword arguments, but it should be error: no parameters may follow a variadic parameter in a closure because removing the argument label doesn't resolve the issue.

It would be great if we can improve this. (not in this PR)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a test case for this, right now both diagnostics are emitted.

let closure6 = {(x: Int..., y z: Int) in } // expected-error {{closure cannot have keyword arguments}}
// expected-error@-1 {{no parameters may follow a variadic parameter in a closure}}

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