Skip to content

Macro definition and expansion in same compilation run can cause name collisions with toplevel definitions #9252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jodersky opened this issue Jun 27, 2020 · 3 comments
Assignees

Comments

@jodersky
Copy link
Contributor

If a macro is expanded by a toplevel function and at another place in the same package but in a different file, and if the macro is defined in the same compilation run, a name collision appears.

Consider the following example. Assume these 3 files:

  • the macro definition itself, Macro.scala:

    object Macro {
      inline def expand(): Unit = ${impl}
      def impl(using scala.quoted.QuoteContext) = '{???}
    }
    
  • the first expansion site, Clazz.scala:

    class Clazz {
      def foo = Macro.expand()
    }
    
  • the second expansion site, toplevel.scala:

    def fct: Unit = Macro.expand()
    

Compiling all three files at once will produce the following error.

dotc Macro.scala Clazz.scala toplevel.scala:

-- Error: toplevel.scala:1:0 ---------------------------------------------------
1 |def fct: Unit = Macro.expand()
  |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |toplevel$package$ is already defined as package object toplevel$package
1 error found

Some notes:

  • compiling them separately works as intended:

    dotc Macro.scala && dotc Clazz.scala toplevel.scala # OK
    dotc Macro.scala Clazz.scala && dotc toplevel.scala # OK
    dotc Macro.scala toplevel.scala && dotc Clazz.scala # OK
    
  • Clazz and fct must be defined in the same package but in different files,
    for this bug to manifest itself.

  • the other expansion site doesn't have to be in a class. It can very well be another toplevel function in a different file. The issue will manifest itself as long as expansions are in different files but in the same package and at least one of them is a toplevel definition.

  • this was observed on version 0.25.0-RC2

  • here's an example project with the above mentioned files: https://github.com/jodersky/dotty-bug

/cc @nicolasstucki @manojo

@nicolasstucki
Copy link
Contributor

It looks like the symbol toplevel$package$ from the previous run is kept which causes the conflict.

@odersky
Copy link
Contributor

odersky commented Jun 28, 2020

@nicolasstucki In this example, do we split compilation into multiple runs by suspending some calls?

@nicolasstucki
Copy link
Contributor

Yes. In the first run we suspend Clazz.scala and toplevel.scala, then in the second run there is the conflict with the symbol of the definition of toplevel$package. Possibly a reference to toplevel$package from Clazz.scala.

odersky added a commit that referenced this issue Jun 29, 2020
Fix #9252: Refine test for conflicting package objects
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants