scala/scala3

Incremental compiler does not account for top level definition conflicts

Opened this issue · 2 comments

Compiler version

any

Minimized code

Split across 2 files:
A.scala:

package test

object A
// def a() = ??? // [1]

B.scala

package test

object B
def a() = ???

scalac will not show the issue - use scalacli with a build server (or another built tool):

  1. scala-cli A.scala B.scala
  2. uncomment [1]
  3. scala-cli A.scala B.scala

Output

no error, successful compilation

Expectation

Same error as when initially compiling A.scala and B.scala with uncommented [1], where we get:

[error] ./B.scala:4:1
[error] a is already defined as method a in /Users/jchyb/workspace/scala3/A.scala
[error] 
[error] Note that overloaded methods must all be defined in the same group of toplevel definitions
[error] def a() = ???
[error] ^^^^^^^^^^^^^

After some research I do not really think it is an issue with a compiler, but it seems moreso with zinc. Conflicts in objects/classes are handled correctly there, but in a somewhat surprising way, where after incrementally compiling the second scala file with a conflicting object/class, zinc chooses to recompile both conflicting classes again, and the compiler then is able to throw the error. What I think happens is that zinc stores links between classes and source files, and if any class is changed it recompiles the linked source files, if there are multiple.

In scala 3, in the ExtractDependencies phase we emit the top level methods as a part of generated package object classes, because of which the above behavior does not occur for those. Ideally, I imagine zinc would be able to unpack those top level methods by itself and create the links to the source files (and I imagine changing anything in the compiler here might end up being a dangerous API change).

I do not have much experience with zinc and incremental compilation, so I can't really speak on what is expected and what not, so I thought it would be safer to issue this here for now.

Seems to duplicate #18447 which like every good abecedarium ends in zinc.