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):
- scala-cli A.scala B.scala
- uncomment [1]
- 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.