summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.sbt3
-rw-r--r--project/PartestUtil.scala4
-rw-r--r--project/plugins.sbt4
-rw-r--r--spec/_config.yml2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala15
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala11
-rwxr-xr-xtest/files/neg/t10207.check4
-rw-r--r--test/files/neg/t10207.scala16
-rw-r--r--test/files/run/hash-hash-hash-hash.scala5
-rw-r--r--test/files/run/unit-block-hash-hash.scala12
-rw-r--r--test/junit/scala/sys/process/PipedProcessTest.scala30
12 files changed, 72 insertions, 47 deletions
diff --git a/build.sbt b/build.sbt
index 6a74107de5..da823d7df7 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1018,6 +1018,9 @@ commands += Command("partest")(_ => PartestUtil.partestParser((baseDirectory in
("test/it:testOnly -- " + parsed) :: state
}
+// Watch the test files also so ~partest triggers on test case changes
+watchSources ++= PartestUtil.testFilePaths((baseDirectory in ThisBuild).value, (baseDirectory in ThisBuild).value / "test")
+
// Add tab completion to scalac et al.
commands ++= {
val commands =
diff --git a/project/PartestUtil.scala b/project/PartestUtil.scala
index 127dcafefa..6d2c9a4c45 100644
--- a/project/PartestUtil.scala
+++ b/project/PartestUtil.scala
@@ -26,6 +26,10 @@ object PartestUtil {
isParentOf(testBase / srcPath, f, 2) || isParentOf(f, testBase / srcPath, Int.MaxValue)
}
}
+
+ def testFilePaths(globalBase: File, testBase: File): Seq[java.io.File] =
+ (new TestFiles("files", globalBase, testBase)).allTestCases.map(_._1)
+
/** A parser for the custom `partest` command */
def partestParser(globalBase: File, testBase: File): Parser[String] = {
val knownUnaryOptions = List(
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 80aef2c591..ca80c88a9e 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -20,3 +20,7 @@ buildInfoKeys := Seq[BuildInfoKey](buildClasspath)
buildInfoPackage := "scalabuild"
libraryDependencies += "com.typesafe" %% "mima-reporter" % "0.1.13"
+
+concurrentRestrictions in Global := Seq(
+ Tags.limitAll(1) // workaround for https://github.com/sbt/sbt/issues/2970
+)
diff --git a/spec/_config.yml b/spec/_config.yml
index 60e80ee05c..1a67f7de63 100644
--- a/spec/_config.yml
+++ b/spec/_config.yml
@@ -1,7 +1,7 @@
baseurl: /files/archive/spec/2.12
safe: true
lsi: false
-highlighter: null
+highlighter: false
markdown: redcarpet
encoding: utf-8
redcarpet:
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index d948d151a6..dd44366692 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -122,11 +122,16 @@ abstract class SymbolLoaders {
* and give them `completer` as type.
*/
def enterClassAndModule(root: Symbol, name: String, getCompleter: (ClassSymbol, ModuleSymbol) => SymbolLoader) {
- val clazz = newClass(root, name)
- val module = newModule(root, name)
- val completer = getCompleter(clazz, module)
- enterClass(root, clazz, completer)
- enterModule(root, module, completer)
+ val clazz0 = newClass(root, name)
+ val module0 = newModule(root, name)
+ val completer = getCompleter(clazz0, module0)
+ // enterClass/Module may return an existing symbol instead of the ones we created above
+ // this may happen when there's both sources and binaries on the classpath, but the class
+ // name is different from the file name, so the classpath can't match the binary and source
+ // representation. `companionModule/Class` prefers the source version, so we should be careful
+ // to reuse the symbols returned below.
+ val clazz = enterClass(root, clazz0, completer)
+ val module = enterModule(root, module0, completer)
if (!clazz.isAnonymousClass) {
// Diagnostic for SI-7147
def msg: String = {
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index f8f0c193e2..e327a6658c 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -1064,21 +1064,20 @@ abstract class Erasure extends InfoTransform
}
else if (args.isEmpty && interceptedMethods(fn.symbol)) {
if (poundPoundMethods.contains(fn.symbol)) {
- val qual1 = preErase(qual)
// This is unattractive, but without it we crash here on ().## because after
// erasure the ScalaRunTime.hash overload goes from Unit => Int to BoxedUnit => Int.
// This must be because some earlier transformation is being skipped on ##, but so
// far I don't know what. For null we now define null.## == 0.
def staticsCall(methodName: TermName): Tree = {
- val newTree = gen.mkMethodCall(RuntimeStaticsModule, methodName, qual1 :: Nil)
+ val newTree = gen.mkMethodCall(RuntimeStaticsModule, methodName, qual :: Nil)
global.typer.typed(newTree)
}
- qual1.tpe.typeSymbol match {
- case UnitClass | NullClass => BLOCK(qual1, LIT(0))
- case IntClass => qual1
- case s @ (ShortClass | ByteClass | CharClass) => numericConversion(qual1, s)
- case BooleanClass => If(qual1, LIT(true.##), LIT(false.##))
+ qual.tpe.typeSymbol match {
+ case UnitClass | NullClass => LIT(0)
+ case IntClass => qual
+ case s @ (ShortClass | ByteClass | CharClass) => numericConversion(qual, s)
+ case BooleanClass => If(qual, LIT(true.##), LIT(false.##))
case LongClass => staticsCall(nme.longHash)
case FloatClass => staticsCall(nme.floatHash)
case DoubleClass => staticsCall(nme.doubleHash)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 65d1910364..8333d5d295 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4666,19 +4666,20 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val qual1 = typedQualifier(qual)
if (treeInfo.isVariableOrGetter(qual1)) {
if (Statistics.canEnable) Statistics.stopTimer(failedOpEqNanos, opeqStart)
- val erred = qual1.isErroneous || args.exists(_.isErroneous)
+ val erred = qual1.exists(_.isErroneous) || args.exists(_.isErroneous)
if (erred) reportError(error) else {
val convo = convertToAssignment(fun, qual1, name, args)
silent(op = _.typed1(convo, mode, pt)) match {
case SilentResultValue(t) => t
- case err: SilentTypeError => reportError(SilentTypeError(advice1(convo, error.errors, err), error.warnings))
+ case err: SilentTypeError => reportError(
+ SilentTypeError(advice1(convo, error.errors, err), error.warnings)
+ )
}
}
- }
- else {
+ } else {
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart)
val Apply(Select(qual2, _), args2) = tree
- val erred = qual2.isErroneous || args2.exists(_.isErroneous)
+ val erred = qual2.exists(_.isErroneous) || args2.exists(_.isErroneous)
reportError {
if (erred) error else SilentTypeError(advice2(error.errors), error.warnings)
}
diff --git a/test/files/neg/t10207.check b/test/files/neg/t10207.check
new file mode 100755
index 0000000000..3330db44a5
--- /dev/null
+++ b/test/files/neg/t10207.check
@@ -0,0 +1,4 @@
+t10207.scala:14: error: too many arguments (2) for method apply: (key: Int)scala.collection.mutable.ArrayBuffer[String] in trait MapLike
+ m(1, (_ => empty)) ++= AB("eins", "uno")
+ ^
+one error found
diff --git a/test/files/neg/t10207.scala b/test/files/neg/t10207.scala
new file mode 100644
index 0000000000..2dfc5d75c9
--- /dev/null
+++ b/test/files/neg/t10207.scala
@@ -0,0 +1,16 @@
+
+// Was:
+// warning: an unexpected type representation reached the compiler backend
+// Now:
+// error: too many arguments (2) for method apply: (key: Int)scala.collection.mutable.ArrayBuffer[String] in trait MapLike
+
+trait Test {
+ import collection.mutable.{Map=>MMap, ArrayBuffer=>AB}
+
+ val m = MMap((1 -> AB("one")))
+
+ val empty = AB[String]()
+
+ m(1, (_ => empty)) ++= AB("eins", "uno")
+}
+
diff --git a/test/files/run/hash-hash-hash-hash.scala b/test/files/run/hash-hash-hash-hash.scala
deleted file mode 100644
index 08793871a7..0000000000
--- a/test/files/run/hash-hash-hash-hash.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-object Test {
- def main(args: Array[String]): Unit = {
- assert(1.##.## == 1) // was java.lang.NoSuchMethodError: java.lang.Object.$hash$hash()I
- }
-}
diff --git a/test/files/run/unit-block-hash-hash.scala b/test/files/run/unit-block-hash-hash.scala
deleted file mode 100644
index 2708810a71..0000000000
--- a/test/files/run/unit-block-hash-hash.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-object Ex extends Exception
-object Test {
- def ex: Any = throw Ex
- def main(args: Array[String]): Unit = {
- try {
- { ex; () }.##
- sys.error("no exception was thrown")
- } catch {
- case `Ex` =>
- }
- }
-} \ No newline at end of file
diff --git a/test/junit/scala/sys/process/PipedProcessTest.scala b/test/junit/scala/sys/process/PipedProcessTest.scala
index 53f053e9aa..3f403dbe75 100644
--- a/test/junit/scala/sys/process/PipedProcessTest.scala
+++ b/test/junit/scala/sys/process/PipedProcessTest.scala
@@ -7,13 +7,19 @@ import java.io.{InputStream, OutputStream, PipedInputStream, PipedOutputStream,
ByteArrayOutputStream, IOException, Closeable}
import java.lang.reflect.InvocationTargetException
import scala.concurrent.{Await, Future}
-import scala.concurrent.duration.{Duration, SECONDS}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.control.Exception.ignoring
-// Each test normally ends in a moment, but for failure cases, waits until one second.
+// Each test normally ends in a moment, but for failure cases, waits two seconds.
// SI-7350, SI-8768
+// one second wasn't always enough --
+// https://github.com/scala/scala-dev/issues/313
+object TestDuration {
+ import scala.concurrent.duration.{Duration, SECONDS}
+ val Standard = Duration(2, SECONDS)
+}
+
@RunWith(classOf[JUnit4])
class PipedProcessTest {
class ProcessMock(error: Boolean) extends Process {
@@ -81,7 +87,7 @@ class PipedProcessTest {
val f = Future {
p.callRunAndExitValue(source, sink)
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(source.releaseCount == 0)
assert(sink.releaseCount == 0)
assert(a.destroyCount == 0)
@@ -102,7 +108,7 @@ class PipedProcessTest {
p.callRunAndExitValue(source, sink)
}
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(source.releaseCount == 1)
assert(sink.releaseCount == 1)
assert(a.destroyCount == 0)
@@ -123,7 +129,7 @@ class PipedProcessTest {
p.callRunAndExitValue(source, sink)
}
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(source.releaseCount == 1)
assert(sink.releaseCount == 1)
assert(a.destroyCount == 0)
@@ -142,7 +148,7 @@ class PipedProcessTest {
val f = Future {
p.callRunAndExitValue(source, sink)
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(source.releaseCount == 1)
assert(sink.releaseCount == 1)
assert(a.destroyCount == 1)
@@ -161,7 +167,7 @@ class PipedProcessTest {
val f = Future {
p.callRunAndExitValue(source, sink)
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(source.releaseCount == 1)
assert(sink.releaseCount == 1)
assert(a.destroyCount == 1)
@@ -235,7 +241,7 @@ class PipeSourceSinkTest {
source.join()
sink.join()
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(in.closed == true)
assert(out.closed == true)
assert(source.isReleased == true)
@@ -253,7 +259,7 @@ class PipeSourceSinkTest {
source.release()
sink.release()
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(out.closed == true)
assert(source.isReleased == true)
assert(sink.isReleased == true)
@@ -270,13 +276,13 @@ class PipeSourceSinkTest {
source.release()
sink.release()
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(in.closed == true)
assert(source.isReleased == true)
assert(sink.isReleased == true)
}
- // PipeSource and PipeSink must release resources when interrupted during copy streams"
+ // PipeSource and PipeSink must release resources when interrupted during copy streams
@Test
def runloopInterrupted() {
val in = new DebugInfinityInputStream
@@ -290,7 +296,7 @@ class PipeSourceSinkTest {
source.release()
sink.release()
}
- Await.result(f, Duration(1, SECONDS))
+ Await.result(f, TestDuration.Standard)
assert(in.closed == true)
assert(out.closed == true)
assert(source.isReleased == true)