mirror of https://github.com/sbt/sbt.git
Fix incremental compilation problem with package objects inheriting from invalidated sources in a subpackage.
Resolution of https://issues.scala-lang.org/browse/SI-4695 seems to be to deprecate inheriting from a class in a subpackage. This commit is an alternative solution, possibly to be reverted or restricted if resolution of SI-4695 changes or if this proves to be too conservative in practice. Review by @gkossakowski. With separate inheritance/function call dependency tracking, this probably should only pull in package objects with inheritance dependencies on invalidated files.
This commit is contained in:
parent
ea3e5c3548
commit
cf355f1822
|
|
@ -39,7 +39,8 @@ object Incremental
|
|||
else
|
||||
{
|
||||
def debug(s: => String) = if(java.lang.Boolean.getBoolean(incDebugProp)) log.debug(s) else ()
|
||||
val invalidated = expand(invalidatedRaw, allSources, log)
|
||||
val withPackageObjects = invalidatedRaw ++ invalidatedPackageObjects(invalidatedRaw, previous.relations)
|
||||
val invalidated = expand(withPackageObjects, allSources, log)
|
||||
val pruned = prune(invalidated, previous)
|
||||
debug("********* Pruned: \n" + pruned.relations + "\n*********")
|
||||
val fresh = doCompile(invalidated, binaryChanges)
|
||||
|
|
@ -63,6 +64,11 @@ object Incremental
|
|||
}
|
||||
else invalidated
|
||||
|
||||
// Package objects are fragile: if they depend on an invalidated source, get "class file needed by package is missing" error
|
||||
// This might be too conservative: we probably only need package objects for packages of invalidated sources.
|
||||
private[this] def invalidatedPackageObjects(invalidated: Set[File], relations: Relations): Set[File] =
|
||||
invalidated flatMap relations.usesInternalSrc filter { _.getName == "package.scala" }
|
||||
|
||||
/**
|
||||
* Accepts the sources that were recompiled during the last step and functions
|
||||
* providing the API before and after the last step. The functions should return
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package demo.sub
|
||||
|
||||
class A {
|
||||
implicit def x(i: Int): C = new C(i)
|
||||
}
|
||||
class C(i: Int) {
|
||||
def y = i + 1
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package demo.sub
|
||||
|
||||
class A {
|
||||
implicit def x(i: Int): C = new C(i)
|
||||
}
|
||||
class C(i: Int) {
|
||||
def y = i + 2
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package demo
|
||||
|
||||
object B {
|
||||
3.y
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
package object demo extends sub.A {
|
||||
val y = 9
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Here we have a package object (demo) that extends a class in a subpackage (demo.sub.A)
|
||||
# demo.sub.A provides an implicit used by demo.B
|
||||
$ copy-file changes/package.scala src/main/scala/demo/package.scala
|
||||
$ copy-file changes/A1.scala src/main/scala/demo/sub/A.scala
|
||||
$ copy-file changes/B.scala src/main/scala/demo/B.scala
|
||||
> compile
|
||||
|
||||
# When recompiling A, we delete the class files for A
|
||||
# When the demo package object is loaded, scalac complains it can't
|
||||
# find the class files for A. Presumably this occurs because
|
||||
# package object loading occurs early and doesn't see the new A
|
||||
# from source.
|
||||
$ copy-file changes/A2.scala src/main/scala/demo/sub/A.scala
|
||||
> compile
|
||||
Loading…
Reference in New Issue