Skip to content

Compiler plugin between parser and typer combined with macro usage causes duplicate compilation and compile error #18384

Open
@mrdziuban

Description

@mrdziuban

Compiler version

3.3.0, also the latest 3.3.1-RC5 and 3.4.0-RC1-bin-20230809-c5adafc-NIGHTLY

Minimized code

https://github.com/mrdziuban/dotty-compiler-plugin-issue/tree/duplicated-code

The compiler plugin inserts a phase between the parser and the typer, but the phase doesn't do anything. The code in the tests directory defines a simple macro in Macro.scala and a call to the macro in Test.scala.

I believe both the placement of the compiler plugin and the existence of the macro matter -- if I change either one of them, i.e. run the plugin after the typer or remove the macro, then the issue stops happening.

Output

-- [E161] Naming Error: /Users/matt/dotty-compiler-plugin-issue/tests/src/main/scala/Test.scala:3:0
3 |object test {
  |^
  |test is already defined as object test in /Users/matt/dotty-compiler-plugin-issue/tests/src/main/scala/Test.scala

When I enable -Xprint:typer, the full sbt output that shows the duplicated object test looks like this:

[info] [[syntax trees at end of                     typer]] // /Users/matt/dotty-compiler-plugin-issue/tests/src/main/scala/Macro.scala
[info] package example {
[info]   import scala.quoted.*
[info]   final lazy module val Macro$package: example.Macro$package =
[info]     new example.Macro$package()
[info]   final module class Macro$package() extends Object() {
[info]     this: example.Macro$package.type =>
[info]     private[example] def idMacroImpl[A >: Nothing <: Any](
[info]       implicit evidence$1: quoted.Type[A], ctx: quoted.Quotes):
[info]       quoted.Expr[A => A] =
[info]       '{
[info]         {
[info]           def $anonfun(a: A): A =
[info]             {
[info]               a
[info]             }
[info]           closure($anonfun)
[info]         }
[info]       }.apply(ctx)
[info]     inline def idMacro[A >: Nothing <: Any]: A => A =
[info]       ${
[info]         {
[info]           def $anonfun(using evidence$2: quoted.Quotes): quoted.Expr[A => A] =
[info]             example.Macro$package.inline$idMacroImpl[A](
[info]               quoted.Type.of[A](evidence$2), evidence$2)
[info]           closure($anonfun)
[info]         }
[info]       }:(A => A)
[info]     def inline$idMacroImpl[A](implicit evidence$1: quoted.Type[A],
[info]       implicit ctx: quoted.Quotes): quoted.Expr[A => A] =
[info]       example.Macro$package.idMacroImpl[A](evidence$1, ctx)
[info]   }
[info] }
[info] [[syntax trees at end of                     typer]] // /Users/matt/dotty-compiler-plugin-issue/tests/src/main/scala/Test.scala
[info] package example {
[info]   final lazy module val test: example.test = new example.test()
[info]   final module class test() extends Object() { this: example.test.type =>
[info]     val intId: Int => Int = example.idMacro[Int]
[info]   }
[info] }
[error] -- [E161] Naming Error: /Users/matt/dotty-compiler-plugin-issue/tests/src/main/scala/Test.scala:3:0
[error] 3 |object test {
[error]   |^
[error]   |test is already defined as object test in /Users/matt/dotty-compiler-plugin-issue/tests/src/main/scala/Test.scala
[info] [[syntax trees at end of                     typer]] // /Users/matt/dotty-compiler-plugin-issue/tests/src/main/scala/Test.scala
[info] package example {
[info]   final lazy module val test$1: example.test = new example.test()
[info]   final module class test$2() extends Object() { this: example.test.type =>
[info]     val intId: Int => Int = example.idMacro[Int]
[info]   }
[info] }

Expectation

Compilation should succeed

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions