summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/CompilationUnits.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/CompilationUnits.scala')
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala24
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.
*/