To get more detailed info, it helps passing -Xprint:typer as an option to the compiler. That gives:
result of test.scala after typer:
package <empty> {
final lazy module val test$package: test$package$ = new test$package$()
final module class test$package$() extends Object() {
this: test$package.type =>
type ContextFunc = ContextFunction1[Array[Int], Unit]
def test(f: ContextFunc): Unit =
{
val a: Array[Int] = Array.apply(1, [2,3 : Int]*)
f.apply(using a)
intArrayOps(a).foreach[Unit](
{
def $anonfun(x: Any): Unit = println(x)
closure($anonfun)
}
)
}
def updateArr(using a: Array[Int]): Unit = a.update(0, a.apply(0).+(99))
@main() def runApp: Unit =
test(
{
def $anonfun(using evidence$1: Array[Int]): Unit =
{
Tuple3.apply[Int, Unit, Unit](1.+(1), updateArr(evidence$1),
println("hello world")
)
()
}
closure($anonfun)
}
)
}
final class runApp() extends Object() {
<static> def main(args: Array[String]): Unit =
try test$package.runApp catch
{
case error @ _:scala.util.CommandLineParser.ParseError =>
scala.util.CommandLineParser.showError(error)
}
}
}
So what happens here is the following:
The three arguments 1+1, updateArr, println("hello world")
are indeed auto-tupled, so you get
(1+1, updateArr, println("hello world"))
That is typed under a lambda since the expected result type is a context function:
(_: Array[Int]) ?=> (1+1, updateArr, println("hello world"))
Now unit discarding kicks in, yielding
(_: Array[Int]) ?=> { (1+1, updateArr, println("hello world")); () }
Unit discarding is not essential. The same works also if ContextFunc
is defined like this:
type ContextFunc = Array[Int] ?=> Any
What to do about it? I believe the culprit here is clearly auto-tupling. If I compile with -language:noAutopTupling
I get:
sc test.scala -language:noAutoTupling
-- Error: test.scala:13:12 -----------------------------------------------------
13 | test(1+1, updateArr, println("hello world"))
| ^^^^^^^^^
| too many arguments for method test: (f: ContextFunc): Unit
1 error found
We’d like to get rid of auto-tupling. I have tried really hard to do so and have spent considerable time on it. But in the end, the breakage wrt 2.13 was too big a risk. All we could do in 3.0 was remove some of the more egregious pitfalls of auto-tupling. So we could not do all of it yet, but hopefully it will come in the future.
And, please don’t turn this into a feature by exploiting this in clever ways. It will likely cause a lot of problems later when we remove auto-tupling.