diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/CompilationUnits.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/CompilationUnits.scala | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index a2108b8ced..15d365ab8c 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -39,11 +39,31 @@ trait CompilationUnits { self: Global => /** Note: depends now contains toplevel classes. * To get their sourcefiles, you need to dereference with .sourcefile */ - val depends = mutable.HashSet[Symbol]() + private[this] val _depends = mutable.HashSet[Symbol]() + // SBT compatibility (SI-6875) + // + // imagine we have a file named A.scala, which defines a trait named Foo and a module named Main + // Main contains a call to a macro, which calls c.introduceTopLevel to define a mock for Foo + // c.introduceTopLevel creates a virtual file Virt35af32.scala, which contains a class named FooMock extending Foo, + // and macro expansion instantiates FooMock. the stage is now set. let's see what happens next. + // + // without this workaround in scalac or without being patched itself, sbt will think that + // * Virt35af32 depends on A (because it extends Foo from A) + // * A depends on Virt35af32 (because it contains a macro expansion referring to FooMock from Virt35af32) + // + // after compiling A.scala, SBT will notice that it has a new source file named Virt35af32. + // it will also think that this file hasn't yet been compiled and since A depends on it + // it will think that A needs to be recompiled. + // + // recompilation will lead to another macro expansion. that another macro expansion might choose to create a fresh mock, + // producing another virtual file, say, Virtee509a, which will again trick SBT into thinking that A needs a recompile, + // which will lead to another macro expansion, which will produce another virtual file and so on + def depends = if (exists && !source.file.isVirtual) _depends else mutable.HashSet[Symbol]() /** so we can relink */ - val defined = mutable.HashSet[Symbol]() + private[this] val _defined = mutable.HashSet[Symbol]() + def defined = if (exists && !source.file.isVirtual) _defined else mutable.HashSet[Symbol]() /** Synthetic definitions generated by namer, eliminated by typer. */ |