Closed
Description
Compiler version
3.3.2-RC1-bin-20230630-c629090-NIGHTLY and before
Minimized code
The following snippet contains multiple cases obtained by uncommenting one of the commented lines at a time.
object Test {
def foo1(x: Int, y: Int, z: Int) = println((x, y, z))
def foo2(x: Int = 0, y: Int, z: Int) = println((x, y, z))
def bar1(x: Int, ys: Int*) = println((x, ys))
def bar2(x: Int = 0, ys: Int*) = println((x, ys))
def main(args: Array[String]) = {
// foo1(1, y = 2, 3)
// foo2(1, y = 2, 3)
// foo1(y = 1, 2, x = 3)
// foo2(y = 1, 2, x = 3)
// foo1(y = 1, 2, z = 3)
// foo2(y = 1, 2, z = 3)
// foo1(y = 1, 2)
// foo2(y = 1, 2)
// bar1()
// bar2()
// bar1(1)
// bar2(1)
// bar1(x = 1)
// bar2(x = 1)
// bar1(ys = 1)
// bar2(ys = 1)
// bar1(1, 2)
// bar2(1, 2)
// bar1(1, ys = 2)
// bar2(1, ys = 2)
// bar1(x = 1, 2)
// bar2(x = 1, 2)
// bar1(x = 1, ys = 2)
// bar2(x = 1, ys = 2)
// bar1(ys = 1, x = 2)
// bar2(ys = 1, x = 2)
// bar1(1, 2, 3)
// bar2(1, 2, 3)
// bar1(1, ys = 2, 3)
// bar2(1, ys = 2, 3)
// bar1(x = 1, 2, 3)
// bar2(x = 1, 2, 3)
// bar1(x = 1, ys = 2, 3)
// bar2(x = 1, ys = 2, 3)
// bar1(x = 1, 2, ys = 3)
// bar2(x = 1, 2, ys = 3)
// bar1(ys = 1, 2, x = 3)
// bar2(ys = 1, 2, x = 3)
}
}
Output
code | scala 3.nightly | scala 2.13.11 |
---|---|---|
foo1(1, y = 2, 3) | (1,2,3) | (1,2,3) |
foo2(1, y = 2, 3) | (1,2,3) | (1,2,3) |
foo1(y = 1, 2, x = 3) | (3,1,2) | positional after named |
foo2(y = 1, 2, x = 3) | (3,1,2) | positional after named |
foo1(y = 1, 2, z = 3) | missing argument x | positional after named |
foo2(y = 1, 2, z = 3) | too many arguments | positional after named |
foo1(y = 1, 2) | missing argument x | positional after named, missing arguments x, z |
foo2(y = 1, 2) | (0,1,2) | positional after named, missing argument z |
code | scala 3.nightly | scala 2.13.11 |
---|---|---|
bar1() | missing argument x | missing arguments x, ys |
bar2() | (0,ArraySeq()) | def bar2 not compiling; missing argument ys |
bar1(1) | (1,ArraySeq()) | (1,List()) |
bar2(1) | (1,ArraySeq()) | def bar2 not compiling |
bar1(x = 1) | (1,ArraySeq()) | (1,List()) |
bar2(x = 1) | (1,ArraySeq()) | def bar2 not compiling |
bar1(ys = 1) | missing argument x | vararg required exactly once |
bar2(ys = 1) | (0,ArraySeq(1)) | def bar2 not compiling; vararg required exactly once |
bar1(1, 2) | (1,ArraySeq(2)) | (1,ArraySeq(2)) |
bar2(1, 2) | (1,ArraySeq(2)) | def bar2 not compiling |
bar1(1, ys = 2) | (1,ArraySeq(2)) | (1,ArraySeq(2)) |
bar2(1, ys = 2) | (1,ArraySeq(2)) | def bar2 not compiling |
bar1(x = 1, 2) | (1,ArraySeq(2)) | (1,ArraySeq(2)) |
bar2(x = 1, 2) | (1,ArraySeq(2)) | def bar2 not compiling |
bar1(x = 1, ys = 2) | (1,ArraySeq(2)) | (1,ArraySeq(2)) |
bar2(x = 1, ys = 2) | (1,ArraySeq(2)) | def bar2 not compiling |
bar1(ys = 1, x = 2) | (2,ArraySeq(1)) | (2,List(1)) |
bar2(ys = 1, x = 2) | (2,ArraySeq(1)) | def bar2 not compiling |
bar1(1, 2, 3) | (1,ArraySeq(2, 3)) | (1,ArraySeq(2, 3)) |
bar2(1, 2, 3) | (1,ArraySeq(2, 3)) | def bar2 not compiling |
bar1(1, ys = 2, 3) | (1,ArraySeq(2, 3)) | (1,ArraySeq(2, 3)) |
bar2(1, ys = 2, 3) | (1,ArraySeq(2, 3)) | def bar2 not compiling |
bar1(x = 1, 2, 3) | (1,ArraySeq(2, 3)) | (1,ArraySeq(2, 3)) |
bar2(x = 1, 2, 3) | (1,ArraySeq(2, 3)) | def bar2 not compiling |
bar1(x = 1, ys = 2, 3) | (1,ArraySeq(2, 3)) | (1,ArraySeq(2, 3)) |
bar2(x = 1, ys = 2, 3) | (1,ArraySeq(2, 3)) | def bar2 not compiling |
bar1(x = 1, 2, ys = 3) | (1,ArraySeq(3, 2)) | ys already specified |
bar2(x = 1, 2, ys = 3) | (1,ArraySeq(3, 2)) | def bar2 not compiling; ys already specified |
bar1(ys = 2, 3) | missing argument x | positional after named |
bar2(ys = 2, 3) | (0,ArraySeq(2, 3)) | def bar2 not compiling; positional after named |
bar1(ys = 1, 2, x = 3) | (3,ArraySeq(1, 2)) | positional after named |
bar2(ys = 1, 2, x = 3) | (3,ArraySeq(1, 2)) | def bar2 not compiling; positional after named |
Abbreviated error messages explained:
positional after named
-positional after named argument
(scala 2)too many arguments
-too many arguments for method ...
missing argument x
-missing argument for parameter x of method ...
(scala 3),not enough arguments for method ... Unspecified value parameter x
(scala 2)def bar2 not compiling
-a parameter section with a `*`-parameter is not allowed to have default arguments
(scala 2)vararg required exactly once
-when using named arguments, the vararg parameter has to be specified exactly once
Expectation
- IMO scala 2 is right to disallow using unnamed arguments after named ones - otherwise it's quite unclear whether such an argument fills the first missing parameter slot (which I would personally assume, given that such usage is not disallowed completely) or the slot following the previous named parameter (which seems to be the case in scala 3, taking e.g. the behaviour of
foo1(y = 1, 2, x = 3)
into account) - Given that a user knows the current behaviour of the compiler for separate named and unnamed arguments in scala 3, the behaviour for varargs might seem consistent in some way, but otherwise it's also rather surprising. My personal first guess about named vararg argument was that I should pass a sequence like
ys = Seq(2, 3)
instead ofys = 2, 3
, but this doesn't work. Should any of these syntaxes be legal at all? Especially the results forbar2(ys = 2, 3)
andbar2(x = 1, 2, ys = 3)
seem very confusing to me - The error messages for
foo1(y = 1, 2, z = 3)
,foo2(y = 1, 2, z = 3)
,foo1(y = 1, 2)
andbar1(ys = 2, 3)
should be improved - currently it's not clear if the fix would be to add a name to an unnamed argument or to add another (possibly unnamed) argument