Enable name hashing incremental compilation by default.

This commit changes the default value of `IncOptions.nameHashing` to be
set to true. It means, the improved incremental compilation algorithm
known as "name hashing" will be enabled by default.

In order to disable it, users should add this to their sbt configuration:

  incOptions := incOptions.value.withNameHashing(false)

Number of tests has been cleaned up as part of this change. All tests
that were marked as name hashing specific are removed. The list includes:

  * constants-name-hashing
  * import-class-name-hashing
  * java-static-name-hashing
  * macro-name-hashing
  * struct-name-hashing

We'll keep just regular version of those tests. The tests will just
exercise the default algorithm: name hashing. This is the first step
towards phasing out of the old incremental compilation algorithm.

Apart from that, a few tests changed its status due to enabling name
hashing algorithm.

The `constants` test has been marked pending due to issue described in
#1543.

The `import-class` test has been marked as passing because name hashing
tracks dependencies introduced by import statements correctly, now.

The `macro` test has been marked as pending due to issue described in
#1544.

The `struct` test has been marked as pending due to issue described in
#1545.

The `java-static` has been slightly modified to exercise just static field
and not run into the same issue as with `constants` test.

There are no other known issues related to name hashing so we conclude
that name hashing is ready to be shipped to all sbt, Scala IDE and zinc
users.
This commit is contained in:
Grzegorz Kossakowski 2014-08-22 02:08:07 +02:00
parent b202bd6848
commit c440c578fc
35 changed files with 22 additions and 161 deletions

View File

@ -217,7 +217,7 @@ final class IncOptions(
object IncOptions extends Serializable {
private val recompileOnMacroDefDefault: Boolean = true
private val nameHashingDefault: Boolean = false
private val nameHashingDefault: Boolean = true
private val antStyleDefault: Boolean = false
val Default = IncOptions(
// 1. recompile changed sources

View File

@ -1 +0,0 @@
incOptions := incOptions.value.withNameHashing(true)

View File

@ -1 +0,0 @@
object A { final val x = 1 }

View File

@ -1 +0,0 @@
object A { final val x = 2 }

View File

@ -1,4 +0,0 @@
object B
{
def main(args: Array[String]) = assert(args(0).toInt == A.x )
}

View File

@ -1,3 +1,5 @@
# Marked as pending, see https://github.com/sbt/sbt/issues/1543
#
# Tests if source dependencies are tracked properly
# for compile-time constants (like final vals in top-level objects)
# see https://issues.scala-lang.org/browse/SI-7173 for details

View File

@ -1,11 +0,0 @@
# Tests if source dependencies are tracked properly
# for compile-time constants (like final vals in top-level objects)
# see https://issues.scala-lang.org/browse/SI-7173 for details
# why compile-time constants can be tricky to track due to early inlining
$ copy-file changes/B.scala B.scala
$ copy-file changes/A1.scala A.scala
> run 1
$ copy-file changes/A2.scala A.scala
> run 2

View File

@ -1,3 +0,0 @@
package a
class A

View File

@ -1 +0,0 @@
incOptions := incOptions.value.withNameHashing(true)

View File

@ -1,8 +0,0 @@
> compile
# remove class a.A
$ copy-file changes/A.scala A.scala
# 'import a.A' should now fail in B.scala
# succeeds because scalac doesn't track this dependency
-> compile

View File

@ -1,3 +1,6 @@
// this test is specific to the old incremental compilation algorithm
incOptions := incOptions.value.withNameHashing(false)
lazy val verifyDeps = taskKey[Unit]("verify inherited dependencies are properly extracted")
verifyDeps := {

View File

@ -1,3 +1,6 @@
// this test is specific to the old incremental compilation algorithm
incOptions := incOptions.value.withNameHashing(false)
lazy val verifyDeps = taskKey[Unit]("verify inherited dependencies are properly extracted")
verifyDeps := {

View File

@ -1 +0,0 @@
incOptions := incOptions.value.withNameHashing(true)

View File

@ -1,4 +0,0 @@
public class J
{
public static final int x = 3;
}

View File

@ -1,4 +0,0 @@
public class J
{
public static final String x = "3";
}

View File

@ -1,4 +0,0 @@
object S
{
val y: Int = J.x
}

View File

@ -1,24 +0,0 @@
# When a Java class is loaded from a class file and not parsed from a source file, scalac reports
# the statics as an object without a file and so the Analyzer must know to look for the
# object's linked class.
# This test verifies this happens.
# The test compiles a Java class with a static field.
# It then adds a Scala object that references the static field. Because the object only depends on a
# static member and because the Java source is not included in the compilation (since it didn't change),
# this triggers the special case above.
# add and compile the Java source
$ copy-file changes/J1.java src/main/java/J.java
> compile
# add and compile the Scala source
$ copy-file changes/S.scala src/main/scala/S.scala
> compile
# change the Java source so that a compile error should occur if S.scala is also recompiled (which will happen if the dependency was properly recorded)
$ copy-file changes/J2.java src/main/java/J.java
-> compile
# verify it should have failed by doing a full recompilation
> clean
-> compile

View File

@ -1,4 +1,4 @@
public class J
{
public static final int x = 3;
public static final Integer x = 3;
}

View File

@ -1,5 +0,0 @@
package macro
object Client {
Provider.tree(0)
}

View File

@ -1,8 +0,0 @@
package macro
import scala.language.experimental.macros
import scala.reflect.macros._
object Provider {
def tree(args: Any) = macro treeImpl
def treeImpl(c: Context)(args: c.Expr[Any]) = c.universe.reify(args.splice)
}

View File

@ -1,8 +0,0 @@
package macro
import scala.language.experimental.macros
import scala.reflect.macros._
object Provider {
def tree(args: Any) = macro treeImpl
def treeImpl(c: Context)(args: c.Expr[Any]) = sys.error("no macro for you!")
}

View File

@ -1,29 +0,0 @@
import sbt._
import Keys._
object build extends Build {
val defaultSettings = Seq(
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-reflect" % _ ),
incOptions := incOptions.value.withNameHashing(true)
)
lazy val root = Project(
base = file("."),
id = "macro",
aggregate = Seq(macroProvider, macroClient),
settings = Defaults.defaultSettings ++ defaultSettings
)
lazy val macroProvider = Project(
base = file("macro-provider"),
id = "macro-provider",
settings = Defaults.defaultSettings ++ defaultSettings
)
lazy val macroClient = Project(
base = file("macro-client"),
id = "macro-client",
dependencies = Seq(macroProvider),
settings = Defaults.defaultSettings ++ defaultSettings
)
}

View File

@ -1,3 +1,6 @@
# Marked as pending due to StackOverflow error, see
# https://github.com/sbt/sbt/issues/1544 for details
> compile
# replace macro with one that throws an error

View File

@ -1,13 +0,0 @@
> compile
# replace macro with one that throws an error
$ copy-file macro-provider/changes/Provider.scala macro-provider/Provider.scala
> macro-provider/compile
-> macro-client/compile
> clean
-> compile

View File

@ -1,3 +0,0 @@
object A {
def x: Int = 3
}

View File

@ -1,4 +0,0 @@
object B {
def onX(m: { def x: Int } ) =
m.x
}

View File

@ -1,4 +0,0 @@
object C {
def main(args: Array[String]) =
println(B.onX(A))
}

View File

@ -1 +0,0 @@
incOptions := incOptions.value.withNameHashing(true)

View File

@ -1,3 +0,0 @@
object A {
def x: Byte = 3
}

View File

@ -1,6 +0,0 @@
> compile
# modify A.scala so that it does not conform to the structural type in B.scala
$ copy-file changes/A.scala A.scala
-> compile

View File

@ -0,0 +1,9 @@
# Marked as pending because name hashing doesn't support structural types
# in some cases. See: https://github.com/sbt/sbt/issues/1545
> compile
# modify A.scala so that it does not conform to the structural type in B.scala
$ copy-file changes/A.scala A.scala
-> compile

View File

@ -1,6 +0,0 @@
> compile
# modify A.scala so that it does not conform to the structural type in B.scala
$ copy-file changes/A.scala A.scala
-> compile