diff options
-rw-r--r-- | build.sbt | 3 | ||||
-rw-r--r-- | project/PartestUtil.scala | 4 | ||||
-rw-r--r-- | project/plugins.sbt | 4 | ||||
-rw-r--r-- | spec/_config.yml | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala | 15 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 13 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 11 | ||||
-rwxr-xr-x | test/files/neg/t10207.check | 4 | ||||
-rw-r--r-- | test/files/neg/t10207.scala | 16 | ||||
-rw-r--r-- | test/files/run/hash-hash-hash-hash.scala | 5 | ||||
-rw-r--r-- | test/files/run/unit-block-hash-hash.scala | 12 | ||||
-rw-r--r-- | test/junit/scala/sys/process/PipedProcessTest.scala | 30 |
12 files changed, 72 insertions, 47 deletions
@@ -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) |