From ae05f998bf118ca72d9e39857092227456c5da13 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 12 Feb 2023 11:49:21 +0100 Subject: [PATCH] Don't eta expand unary varargs methods A unary varargs method sits between nullary methods that sometimes get a () argument inferred (i.e. for methods coming from Java) and other methods that can be eta expanded. The safest strategy for them is to do neither, and expect either an explicit expected function type, or an explicit argument. That's also what Scala 2 does. Fixes #16820 Reclassifies #14567 to be a neg test (with the error message suggested in the original issue for #14567) --- .../src/dotty/tools/dotc/typer/Typer.scala | 5 ++++- tests/neg/i16820.check | 22 +++++++++++++++++++ tests/neg/i16820.scala | 13 +++++++++++ tests/pos/i14367.scala | 2 +- tests/pos/i14567.scala | 2 -- 5 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 tests/neg/i16820.check create mode 100644 tests/neg/i16820.scala delete mode 100644 tests/pos/i14567.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index a87d6dd7e703..82928894ebca 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3922,7 +3922,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer else defn.functionArity(ptNorm) else val nparams = wtp.paramInfos.length - if nparams > 0 || pt.eq(AnyFunctionProto) then nparams + if nparams > 1 + || nparams == 1 && !wtp.isVarArgsMethod + || pt.eq(AnyFunctionProto) + then nparams else -1 // no eta expansion in this case adaptNoArgsUnappliedMethod(wtp, funExpected, arity) case _ => diff --git a/tests/neg/i16820.check b/tests/neg/i16820.check new file mode 100644 index 000000000000..5f2e82bbf2ef --- /dev/null +++ b/tests/neg/i16820.check @@ -0,0 +1,22 @@ +-- Error: tests/neg/i16820.scala:5:11 ---------------------------------------------------------------------------------- +5 | val x1 = f // error + | ^ + | missing arguments for method f in object Test +-- [E100] Syntax Error: tests/neg/i16820.scala:6:11 -------------------------------------------------------------------- +6 | val x2 = g // error + | ^ + | method g in object Test must be called with () argument + | + | longer explanation available when compiling with `-explain` +-- Error: tests/neg/i16820.scala:8:14 ---------------------------------------------------------------------------------- +8 | val x3 = "".formatted // error + | ^^^^^^^^^^^^ + | missing arguments for method formatted in class String +-- Error: tests/neg/i16820.scala:9:40 ---------------------------------------------------------------------------------- +9 | val x4 = java.nio.file.Paths.get(".").toRealPath // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | missing arguments for method toRealPath in trait Path +-- Error: tests/neg/i16820.scala:13:14 --------------------------------------------------------------------------------- +13 |def test = Foo(3) // error + | ^^^^^^ + | missing arguments for method apply in object Foo diff --git a/tests/neg/i16820.scala b/tests/neg/i16820.scala new file mode 100644 index 000000000000..7a93f3a5d355 --- /dev/null +++ b/tests/neg/i16820.scala @@ -0,0 +1,13 @@ +object Test: + def f(xs: Int*) = xs.sum + def g() = 1 + + val x1 = f // error + val x2 = g // error + + val x3 = "".formatted // error + val x4 = java.nio.file.Paths.get(".").toRealPath // error + +// #14567 +case class Foo(x: Int)(xs: String*) +def test = Foo(3) // error diff --git a/tests/pos/i14367.scala b/tests/pos/i14367.scala index d74f0aa8373e..3319e705b741 100644 --- a/tests/pos/i14367.scala +++ b/tests/pos/i14367.scala @@ -1,5 +1,5 @@ def m(i: Int*) = i.sum -val f1 = m +val f1: Seq[Int] => Int = m val f2 = i => m(i*) def n(i: Seq[Int]) = i.sum diff --git a/tests/pos/i14567.scala b/tests/pos/i14567.scala deleted file mode 100644 index fe47279c07b1..000000000000 --- a/tests/pos/i14567.scala +++ /dev/null @@ -1,2 +0,0 @@ -case class Foo(x: Int)(xs: String*) -def test = Foo(3)