You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
These races could be observed by running:
dotty-compiler-bootstrapped/test-only *.CompilationTests
These never happened on the CI so far because the order in which the
classes are run is not deterministic and we got "lucky" that the first
tests running the compiler did not use parallelism.
The races were caused by a combination of multiple factors:
- The new classpath implementation imported from 2.12 has a shared
global cache of ClassPath instances (see ZipAndJarFileLookupFactory.scala)
- If multiple threads try to initialize a lazy val in dotty, only one
will succeed and the other will get null (in scalac, each thread will
redo the initialization)
- The classpath implementation relies on code from scala.reflect.io that
was recently imported into dotty, this code contains fields with lazy vals.
The race with the lazy val in ZipArchive was easy to fix since it
immediately lead to NullPointerException, but the one in AbstractFile
was much harder to find because the only method called on "lazy val
extension" is `==` which works with null. This suggests that we should
implement a compiler option to check for lazy val races at runtime.
In both cases we fixed the issue by simply dropping the `lazy` instead
of adding an `@volatile`, for ZipArchive I cannot think of a usecase
where you would not want to force the lazy val, and for `AbstractFile`
the cost of always computing the extension is probably less than adding
a lock.
0 commit comments