From e42d883c99c8f6747d78650e3683a228e9962342 Mon Sep 17 00:00:00 2001 From: Oliver Bracevac Date: Sun, 6 Oct 2024 23:53:06 +0200 Subject: [PATCH] Fix rewrite logic for old ` _` syntax A rewrite would previously produce uncompilable code if the access path to the eta-expanded function goes through at least one `def`. Fixes #21394 --- .../src/dotty/tools/dotc/typer/Migrations.scala | 9 ++++++--- .../dotty/tools/dotc/CompilationTests.scala | 1 + tests/rewrites/i21394.check | 17 +++++++++++++++++ tests/rewrites/i21394.scala | 17 +++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 tests/rewrites/i21394.check create mode 100644 tests/rewrites/i21394.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Migrations.scala b/compiler/src/dotty/tools/dotc/typer/Migrations.scala index 7f27f27112a0..f0d1d235a19c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Migrations.scala +++ b/compiler/src/dotty/tools/dotc/typer/Migrations.scala @@ -71,10 +71,13 @@ trait Migrations: } nestedCtx.typerState.commit() + def functionPrefixSuffix(arity: Int) = if (arity > 0) ("", "") else ("(() => ", "())") + lazy val (prefix, suffix) = res match { - case Block(mdef @ DefDef(_, vparams :: Nil, _, _) :: Nil, _: Closure) => - val arity = vparams.length - if (arity > 0) ("", "") else ("(() => ", "())") + case Block(DefDef(_, vparams :: Nil, _, _) :: Nil, _: Closure) => + functionPrefixSuffix(vparams.length) + case Block(ValDef(_, _, _) :: Nil, Block(DefDef(_, vparams :: Nil, _, _) :: Nil, _: Closure)) => + functionPrefixSuffix(vparams.length) case _ => ("(() => ", ")") } diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 0c5d5764949a..d7ef7f6f6085 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -63,6 +63,7 @@ class CompilationTests { compileFile("tests/rewrites/rewrites.scala", defaultOptions.and("-source", "3.0-migration").and("-rewrite", "-indent")), compileFile("tests/rewrites/rewrites3x.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/rewrites3x-fatal-warnings.scala", defaultOptions.and("-rewrite", "-source", "future-migration", "-Xfatal-warnings")), + compileFile("tests/rewrites/i21394.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/uninitialized-var.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/with-type-operator.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/private-this.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), diff --git a/tests/rewrites/i21394.check b/tests/rewrites/i21394.check new file mode 100644 index 000000000000..50e6ab0901b6 --- /dev/null +++ b/tests/rewrites/i21394.check @@ -0,0 +1,17 @@ +trait Container: + def loopDef: Container + val loopVal: Container + def fun(x: Int)(y: Int): Int + +def test(c: Container): Int = + use(c.fun) + + use(c.loopDef.fun) + + use(c.loopVal.fun) + + use(c.loopDef.loopDef.fun) + + use(c.loopVal.loopVal.fun) + + use(c.loopVal.loopDef.fun) + + use(c.loopDef.loopVal.fun) + + use(c.loopVal.loopDef.loopVal.fun) + + use(c.loopVal.loopDef.loopVal.loopDef.fun) + +def use(f: Int => Int => Int): Int = ??? \ No newline at end of file diff --git a/tests/rewrites/i21394.scala b/tests/rewrites/i21394.scala new file mode 100644 index 000000000000..33f183fbed48 --- /dev/null +++ b/tests/rewrites/i21394.scala @@ -0,0 +1,17 @@ +trait Container: + def loopDef: Container + val loopVal: Container + def fun(x: Int)(y: Int): Int + +def test(c: Container): Int = + use(c.fun _) + + use(c.loopDef.fun _) + + use(c.loopVal.fun _) + + use(c.loopDef.loopDef.fun _) + + use(c.loopVal.loopVal.fun _) + + use(c.loopVal.loopDef.fun _) + + use(c.loopDef.loopVal.fun _) + + use(c.loopVal.loopDef.loopVal.fun _) + + use(c.loopVal.loopDef.loopVal.loopDef.fun _) + +def use(f: Int => Int => Int): Int = ??? \ No newline at end of file