From cb5daf3a5d9ab8195746e21801c3300d78efb52c Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 20 Feb 2016 22:51:12 -0800 Subject: [PATCH 001/153] SI-9665 Backquoted vbar in extractor pattern Allow an infix extractor named `|`, when backquoted. --- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 4 ++-- test/files/pos/t9665.scala | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 test/files/pos/t9665.scala diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 831a0412cdaa..53cd2f6d59ed 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1966,8 +1966,8 @@ self => case _ => EmptyTree } def loop(top: Tree): Tree = reducePatternStack(base, top) match { - case next if isIdentExcept(raw.BAR) => pushOpInfo(next) ; loop(simplePattern(badPattern3)) - case next => next + case next if isIdent && !isRawBar => pushOpInfo(next) ; loop(simplePattern(badPattern3)) + case next => next } checkWildStar orElse stripParens(loop(top)) } diff --git a/test/files/pos/t9665.scala b/test/files/pos/t9665.scala new file mode 100644 index 000000000000..1aa7a5d459f1 --- /dev/null +++ b/test/files/pos/t9665.scala @@ -0,0 +1,7 @@ + +object | { def unapply(x: (Any, Any)) = Some(x) } + +trait Test { + def f() = (1,2) match { case 1 `|` 2 => } + def g() = 2 match { case 1 | 2 => } +} From 5fd8483d53521f17c1a697fdf419d35f1cacfac6 Mon Sep 17 00:00:00 2001 From: Taras Boiko Date: Sun, 20 Mar 2016 15:34:33 +0200 Subject: [PATCH 002/153] Added applyOrElse to MapLike This overrides default implementation from PartialFunction which used both contains(x) and get(x) with getOrElse. --- src/library/scala/collection/MapLike.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala index 4ac87b29a90e..d4d85c43ec66 100644 --- a/src/library/scala/collection/MapLike.scala +++ b/src/library/scala/collection/MapLike.scala @@ -158,6 +158,10 @@ self => */ def isDefinedAt(key: A) = contains(key) + override /*PartialFunction*/ + def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = + getOrElse(x, default(x)) + /** Collects all keys of this map in a set. * @return a set containing all keys of this map. */ From 9ec6278e05f6acd471473342067e922cb85293d6 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Tue, 19 Apr 2016 11:35:40 +0100 Subject: [PATCH 003/153] SI-9760 Fix for higher-kinded GADT refinement --- .../scala/tools/nsc/typechecker/Infer.scala | 1 - test/files/pos/hkgadt.scala | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/hkgadt.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index dc91d23011c9..7112edd75d0e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1257,7 +1257,6 @@ trait Infer extends Checkable { def isFreeTypeParamOfTerm(sym: Symbol) = ( sym.isAbstractType && sym.owner.isTerm - && !sym.info.bounds.exists(_.typeParams.nonEmpty) ) // Intentionally *not* using `Type#typeSymbol` here, which would normalize `tp` diff --git a/test/files/pos/hkgadt.scala b/test/files/pos/hkgadt.scala new file mode 100644 index 000000000000..efd7d3df21a4 --- /dev/null +++ b/test/files/pos/hkgadt.scala @@ -0,0 +1,18 @@ +package test + +object HKGADT { + sealed trait Foo[F[_]] + final case class Bar() extends Foo[List] + + def frob[F[_]](foo: Foo[F]): F[Int] = + foo match { + case Bar() => + List(1) + } + + sealed trait Foo1[F] + final case class Bar1() extends Foo1[Int] + def frob1[A](foo: Foo1[A]) = foo match { + case Bar1() => 1 + } +} From fa65623cd8d4e60368126fc958c7185ca5706a6b Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Wed, 20 Apr 2016 10:37:38 +0100 Subject: [PATCH 004/153] Added missing result type to test. --- test/files/pos/hkgadt.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/files/pos/hkgadt.scala b/test/files/pos/hkgadt.scala index efd7d3df21a4..0f3739f4d400 100644 --- a/test/files/pos/hkgadt.scala +++ b/test/files/pos/hkgadt.scala @@ -12,7 +12,7 @@ object HKGADT { sealed trait Foo1[F] final case class Bar1() extends Foo1[Int] - def frob1[A](foo: Foo1[A]) = foo match { + def frob1[A](foo: Foo1[A]): A = foo match { case Bar1() => 1 } } From 56c5d92236daf8a8094429072ec70cf830fd10ac Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Mon, 21 Mar 2016 13:21:19 -0700 Subject: [PATCH 005/153] Add JMH to the benchmark framework. Add an example benchmark for OpenHashMap. --- test/benchmarks/.gitignore | 6 ++ test/benchmarks/README.md | 65 ++++++++++++++++ test/benchmarks/build.sbt | 8 ++ test/benchmarks/project/plugins.sbt | 1 + .../mutable/OpenHashMapBenchmark.scala | 76 +++++++++++++++++++ 5 files changed, 156 insertions(+) create mode 100644 test/benchmarks/.gitignore create mode 100644 test/benchmarks/README.md create mode 100644 test/benchmarks/build.sbt create mode 100644 test/benchmarks/project/plugins.sbt create mode 100644 test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala diff --git a/test/benchmarks/.gitignore b/test/benchmarks/.gitignore new file mode 100644 index 000000000000..6e3ddad6d22c --- /dev/null +++ b/test/benchmarks/.gitignore @@ -0,0 +1,6 @@ +/project/project/ +/project/target/ +/target/ + +# what appears to be a Scala IDE-generated file +.cache-main diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md new file mode 100644 index 000000000000..99b358dd99ef --- /dev/null +++ b/test/benchmarks/README.md @@ -0,0 +1,65 @@ +# Scala library benchmarks + +This directory is a standalone SBT project +that makes use of the [SBT plugin for JMH](https://github.com/ktoso/sbt-jmh), +with the usual directory structure: +source code for the benchmarks, which utilize [JMH](http://openjdk.java.net/projects/code-tools/jmh/), +should be placed in `src/main/scala`. + +The benchmarks require first building Scala into `../../build/pack`. +They can then be (built and) run from `sbt` with "`jmh:run`". +"`jmh:run -h`" displays the usual JMH options available. + +## some useful HotSpot options +Adding these to the `jmh:run` command line may help if you're using the HotSpot (Oracle, OpenJDK) compiler. +They require prefixing with `-jvmArgs`. +See [the Java documentation](http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html) for more options. + +### viewing JIT compilation events +Adding `-XX:+PrintCompilation` shows when Java methods are being compiled or deoptimized. +At the most basic level, +these messages will tell you whether the code that you're measuring is still being tuned, +so that you know whether you're running enough warm-up iterations. +See [Kris Mok's notes](https://gist.github.com/rednaxelafx/1165804#file-notes-md) to interpret the output in detail. + +### consider GC events +If you're not explicitly performing `System.gc()` calls outside of your benchmarking code, +you should add the JVM option `-verbose:gc` to understand the effect that GCs may be having on your tests. + +### "diagnostic" options +These require the `-XX:+UnlockDiagnosticVMOptions` JVM option. + +#### viewing inlining events +Add `-XX:+PrintInlining`. + +#### viewing the disassembled code +To show the assembly code corresponding to the code generated by the JIT compiler for specific methods, +add `-XX:CompileCommand=print,scala.collection.mutable.OpenHashMap::*`, +for example, to show all of the methods in the `scala.collection.mutable.OpenHashMap` class. +If you're running OpenJDK, you may need to install the disassembler library (`hsdis-amd64.so` for the `amd64` architecture). +In Debian, this is available in the `libhsdis0-fcml` package. + +To show it for _all_ methods, add `-XX:+PrintAssembly`. +(This is usually excessive.) + +## useful reading +* [OpenJDK advice on microbenchmarks](https://wiki.openjdk.java.net/display/HotSpot/MicroBenchmarks) +* "[Measuring performance](http://docs.scala-lang.org/overviews/parallel-collections/performance.html)" of Scala parallel collections +* Brian Goetz's "Java theory and practice" articles: + * "[Dynamic compilation and performance measurement](http://www.ibm.com/developerworks/java/library/j-jtp12214/)" + * "[Anatomy of a flawed benchmark](http://www.ibm.com/developerworks/java/library/j-jtp02225/)" + +## legacy frameworks + +An older version of the benchmarking framework is still present in this directory, in the following locations: + +
+
bench
+
A script to run the old benchmarks.
+
source.list
+
A temporary file used by bench.
+
src/scala/
+
The older benchmarks, including the previous framework.
+
+ +Another, older set of benchmarks is present in `../benchmarking/`. diff --git a/test/benchmarks/build.sbt b/test/benchmarks/build.sbt new file mode 100644 index 000000000000..92a5fce177d2 --- /dev/null +++ b/test/benchmarks/build.sbt @@ -0,0 +1,8 @@ +scalaHome := Some(file("../../build/pack")) + +lazy val root = (project in file(".")). + enablePlugins(JmhPlugin). + settings( + name := "test-benchmarks", + version := "0.0.1" + ) diff --git a/test/benchmarks/project/plugins.sbt b/test/benchmarks/project/plugins.sbt new file mode 100644 index 000000000000..f5319fb18747 --- /dev/null +++ b/test/benchmarks/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.6") diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala new file mode 100644 index 000000000000..eeea8f6508df --- /dev/null +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala @@ -0,0 +1,76 @@ +package scala.collection.mutable; + +import java.util.concurrent.TimeUnit +import org.openjdk.jmh.annotations._ + +private object OpenHashMapBenchmark { + /** State container for the `put()` bulk calling tests. + * + * Provides a thread-scoped map, so that allocation for the hash table will be done + * in the first warm-up iteration, not during measurement. + * + * Performs a GC after every invocation, so that only the GCs caused by the invocation + * contribute to the measurement. + */ + @State(Scope.Thread) + class BulkPutState { + val map = new OpenHashMap[Int,Int].empty + + @TearDown(Level.Invocation) + def teardown { map.clear(); System.gc() } + } +} + +/** Benchmark for the library's [[OpenHashMap]]. + * + * The `put()` calls are tested by looping to the size desired for the map; + * instead of using the JMH harness, which iterates for a fixed length of time. + */ +@BenchmarkMode(Array(Mode.AverageTime)) +@Threads(1) +@Fork(1) +@Warmup(iterations = 20) +@Measurement(iterations = 20) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) +class OpenHashMapBenchmark { + import OpenHashMapBenchmark._ + + @Param(Array("100", "250", "1000", "2500", "10000", "25000", "100000", "250000", "1000000", "2500000", + "5000000", "7500000", "10000000", "25000000")) + var size: Int = _ + + /** Put elements into the given map. */ + private[this] def put_Int(map: OpenHashMap[Int,Int], from: Int, to: Int) { + var i = from + while (i <= to) { // using a `for` expression instead adds significant overhead + map.put(i, i) + i += 1 + } + } + + /** Test putting elements to a map of `Int` to `Int`. */ + @Benchmark + def put_Int(state: BulkPutState) { put_Int(state.map, 1, size) } + + /** Test putting and removing elements to a growing map of `Int` to `Int`. */ + @Benchmark + def put_remove_Int(state: BulkPutState) { + val blocks = 50 // should be a factor of `size` + val totalPuts = 2 * size // add twice as many, because we remove half of them + val blockSize: Int = totalPuts / blocks + var base = 0 + while (base < totalPuts) { + put_Int(state.map, base + 1, base + blockSize) + + // remove every other entry + var i = base + 1 + while (i <= base + blockSize) { + state.map.remove(i) + i += 2 + } + + base += blockSize + } + } +} From 303130b81599528db35d9612fff42cf7e570e15a Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Tue, 22 Mar 2016 23:12:31 -0700 Subject: [PATCH 006/153] Add a reference to Doug Lea's benchmarks. --- test/benchmarks/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md index 99b358dd99ef..aea72e90edf9 100644 --- a/test/benchmarks/README.md +++ b/test/benchmarks/README.md @@ -44,10 +44,11 @@ To show it for _all_ methods, add `-XX:+PrintAssembly`. ## useful reading * [OpenJDK advice on microbenchmarks](https://wiki.openjdk.java.net/display/HotSpot/MicroBenchmarks) -* "[Measuring performance](http://docs.scala-lang.org/overviews/parallel-collections/performance.html)" of Scala parallel collections * Brian Goetz's "Java theory and practice" articles: * "[Dynamic compilation and performance measurement](http://www.ibm.com/developerworks/java/library/j-jtp12214/)" * "[Anatomy of a flawed benchmark](http://www.ibm.com/developerworks/java/library/j-jtp02225/)" +* [Doug Lea's JSR 166 benchmarks](http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/loops/) +* "[Measuring performance](http://docs.scala-lang.org/overviews/parallel-collections/performance.html)" of Scala parallel collections ## legacy frameworks From e1b58ccafc598c06b8011e3e0f411f6e91b99353 Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Wed, 23 Mar 2016 12:07:00 -0700 Subject: [PATCH 007/153] Add get() tests to OpenHashMap, reduce timing artifacts. In order to get a better exploration of the variance of tests in a limited time, I've reduced the number of measurement iterations and increased the number of forks. By sight, the measurement iterations seemed pretty consistent within a trial, whereas they would vary widely on occasional forks. I extended testing down to 50-entry maps, to explore the rise in service times that I was seeing at small scale. This is probably a timing artifact, from too-short invocations, since I'm using @Level.Invocation in the put() tests. To fix that, I enlarged the unit of testing, by creating multiple, sometimes thousands, of maps for the invocation to fill. This has also changed the test from filling a previously-filled map, to filling a new, but sufficiently sized map. The put()/remove() test now performs much worse (on a more realistic scenario). This also adds a couple tests for calling get() against a map that's been filled only with put()s, or with a mix of put() and remove(). --- .../mutable/OpenHashMapBenchmark.scala | 179 ++++++++++++++---- 1 file changed, 144 insertions(+), 35 deletions(-) diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala index eeea8f6508df..73ab5e40d0ce 100644 --- a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala @@ -2,46 +2,104 @@ package scala.collection.mutable; import java.util.concurrent.TimeUnit import org.openjdk.jmh.annotations._ +import org.openjdk.jmh.infra.Blackhole +import org.openjdk.jmh.infra.BenchmarkParams +/** Utilities for the [[OpenHashMapBenchmark]]. + * + * The method calls are tested by looping to the size desired for the map; + * instead of using the JMH harness, which iterates for a fixed length of time. + */ private object OpenHashMapBenchmark { /** State container for the `put()` bulk calling tests. * - * Provides a thread-scoped map, so that allocation for the hash table will be done - * in the first warm-up iteration, not during measurement. + * Provides an array of adequately-sized, empty maps to each invocation, + * so that hash table allocation won't be done during measurement. * - * Performs a GC after every invocation, so that only the GCs caused by the invocation - * contribute to the measurement. + * Empties the map and performs a GC after every invocation, + * so that only the GCs caused by the invocation contribute to the measurement. */ @State(Scope.Thread) + @AuxCounters class BulkPutState { + /** A lower-bound estimate of the number of nanoseconds per `put()` call */ + private[this] val nanosPerPut: Double = 5 + + /** Minimum number of nanoseconds per invocation, so as to avoid timing artifacts. */ + private[this] val minNanosPerInvocation = 1000000 // one millisecond + + /** The minimum number of `put()` calls to make per invocation, so as to avoid timing artifacts. */ + private[this] val minPutsPerInvocation = minNanosPerInvocation / nanosPerPut + + /** Size of the maps created in this trial. */ + private[this] var size: Int = _ + + /** Number of maps created in each invocation; the size of `maps`. */ + private[this] var n: Int = _ + + /** Number of operations performed in the current invocation. */ + var operations: Int = _ + + var maps: Array[OpenHashMap[Int,Int]] = null + + @Setup + def threadSetup(params: BenchmarkParams) { + size = params.getParam("size").toInt + n = math.ceil(minPutsPerInvocation / size).toInt + maps = new Array(n) + } + + @Setup(Level.Iteration) + def iterationSetup { + operations = 0 + } + + @Setup(Level.Invocation) + def setup { + for (i <- 0 until n) maps(i) = new OpenHashMap[Int,Int](size) + operations += size * n + System.gc() // clean up after last invocation + } + } + + /** State container for the `get()` bulk calling tests. + * + * Provides a thread-scoped map of the expected size. + * Performs a GC after loading the map. + */ + @State(Scope.Thread) + class BulkGetState { val map = new OpenHashMap[Int,Int].empty - - @TearDown(Level.Invocation) - def teardown { map.clear(); System.gc() } + + /** Load the map with keys from `1` to `size`. */ + @Setup + def setup(params: BenchmarkParams) { + val size = params.getParam("size").toInt + put_Int(map, 1, size) + System.gc() + } } -} -/** Benchmark for the library's [[OpenHashMap]]. - * - * The `put()` calls are tested by looping to the size desired for the map; - * instead of using the JMH harness, which iterates for a fixed length of time. - */ -@BenchmarkMode(Array(Mode.AverageTime)) -@Threads(1) -@Fork(1) -@Warmup(iterations = 20) -@Measurement(iterations = 20) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -class OpenHashMapBenchmark { - import OpenHashMapBenchmark._ + /** State container for the `get()` bulk calling tests with deleted entries. + * + * Provides a thread-scoped map of the expected size, from which entries have been removed. + * Performs a GC after loading the map. + */ + @State(Scope.Thread) + class BulkRemovedGetState { + val map = new OpenHashMap[Int,Int].empty - @Param(Array("100", "250", "1000", "2500", "10000", "25000", "100000", "250000", "1000000", "2500000", - "5000000", "7500000", "10000000", "25000000")) - var size: Int = _ + /** Load the map with keys from `1` to `size`, removing half of them. */ + @Setup + def setup(params: BenchmarkParams) { + val size = params.getParam("size").toInt + put_remove_Int(map, size) + System.gc() + } + } /** Put elements into the given map. */ - private[this] def put_Int(map: OpenHashMap[Int,Int], from: Int, to: Int) { + private def put_Int(map: OpenHashMap[Int,Int], from: Int, to: Int) { var i = from while (i <= to) { // using a `for` expression instead adds significant overhead map.put(i, i) @@ -49,28 +107,79 @@ class OpenHashMapBenchmark { } } - /** Test putting elements to a map of `Int` to `Int`. */ - @Benchmark - def put_Int(state: BulkPutState) { put_Int(state.map, 1, size) } - - /** Test putting and removing elements to a growing map of `Int` to `Int`. */ - @Benchmark - def put_remove_Int(state: BulkPutState) { + /** Put elements into the given map, removing half of them as they're added. + * + * @param size number of entries to leave in the map on return + */ + def put_remove_Int(map: OpenHashMap[Int,Int], size: Int) { val blocks = 50 // should be a factor of `size` val totalPuts = 2 * size // add twice as many, because we remove half of them val blockSize: Int = totalPuts / blocks var base = 0 while (base < totalPuts) { - put_Int(state.map, base + 1, base + blockSize) + put_Int(map, base + 1, base + blockSize) // remove every other entry var i = base + 1 while (i <= base + blockSize) { - state.map.remove(i) + map.remove(i) i += 2 } base += blockSize } } + + /** Get elements from the given map. */ + def get_Int(map: OpenHashMap[Int,Int], size: Int, bh: Blackhole) { + var i = 1 + while (i <= size) { + bh.consume(map.get(i).getOrElse(0)) + i += 1 + } + } +} + +/** Benchmark for the library's [[OpenHashMap]]. */ +@BenchmarkMode(Array(Mode.AverageTime)) +@Fork(10) +@Threads(1) +@Warmup(iterations = 20) +@Measurement(iterations = 6) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +class OpenHashMapBenchmark { + import OpenHashMapBenchmark._ + + @Param(Array("50", "100", "250", "1000", "2500", "10000", "25000", "100000", "250000", "1000000", "2500000", + "5000000", "7500000", "10000000", "25000000")) + var size: Int = _ + + /** Test putting elements to a map of `Int` to `Int`. */ + @Benchmark + def put_Int(state: BulkPutState) { + var i = 0 + while (i < state.maps.length) { + OpenHashMapBenchmark.put_Int(state.maps(i), 1, size) + i += 1 + } + } + + /** Test putting and removing elements to a growing map of `Int` to `Int`. */ + @Benchmark + def put_remove_Int(state: BulkPutState) { + var i = 0 + while (i < state.maps.length) { + OpenHashMapBenchmark.put_remove_Int(state.maps(i), size) + i += 1 + } + } + + /** Test getting elements from a map of `Int` to `Int`. */ + @Benchmark + def put_get_Int(state: BulkGetState, bh: Blackhole) = OpenHashMapBenchmark.get_Int(state.map, size, bh) + + /** Test getting elements from a map of `Int` to `Int` from which elements have been removed. */ + @Benchmark + def put_remove_get_Int(state: BulkRemovedGetState, bh: Blackhole) = OpenHashMapBenchmark.get_Int(state.map, size, bh) } From b88933eb84f1f1f5215b0feb43f4ecfc12c8847d Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Fri, 25 Mar 2016 21:44:50 -0700 Subject: [PATCH 008/153] Benchmark the OpenHashMap memory usage. Also add sbteclipse to the benchmark project. --- test/benchmarks/.gitignore | 8 +++++ test/benchmarks/build.sbt | 5 ++- test/benchmarks/project/plugins.sbt | 1 + .../mutable/OpenHashMapBenchmark.scala | 32 +++++++++++++------ 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/test/benchmarks/.gitignore b/test/benchmarks/.gitignore index 6e3ddad6d22c..ce4d893417db 100644 --- a/test/benchmarks/.gitignore +++ b/test/benchmarks/.gitignore @@ -4,3 +4,11 @@ # what appears to be a Scala IDE-generated file .cache-main + +# standard Eclipse output directory +/bin/ + +# sbteclipse-generated Eclipse files +/.classpath +/.project +/.settings/ diff --git a/test/benchmarks/build.sbt b/test/benchmarks/build.sbt index 92a5fce177d2..2959e4986ad2 100644 --- a/test/benchmarks/build.sbt +++ b/test/benchmarks/build.sbt @@ -1,8 +1,11 @@ scalaHome := Some(file("../../build/pack")) +scalaVersion := "2.11.8" +scalacOptions += "-feature" lazy val root = (project in file(".")). enablePlugins(JmhPlugin). settings( name := "test-benchmarks", - version := "0.0.1" + version := "0.0.1", + libraryDependencies += "org.openjdk.jol" % "jol-core" % "0.4" ) diff --git a/test/benchmarks/project/plugins.sbt b/test/benchmarks/project/plugins.sbt index f5319fb18747..e11aa29f3bfc 100644 --- a/test/benchmarks/project/plugins.sbt +++ b/test/benchmarks/project/plugins.sbt @@ -1 +1,2 @@ +addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0") addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.6") diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala index 73ab5e40d0ce..13be9e6206f2 100644 --- a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala @@ -4,6 +4,9 @@ import java.util.concurrent.TimeUnit import org.openjdk.jmh.annotations._ import org.openjdk.jmh.infra.Blackhole import org.openjdk.jmh.infra.BenchmarkParams +import org.openjdk.jol.info.GraphLayout +import org.openjdk.jol.info.GraphWalker +import org.openjdk.jol.info.GraphVisitor /** Utilities for the [[OpenHashMapBenchmark]]. * @@ -15,9 +18,11 @@ private object OpenHashMapBenchmark { * * Provides an array of adequately-sized, empty maps to each invocation, * so that hash table allocation won't be done during measurement. - * - * Empties the map and performs a GC after every invocation, + * Provides enough maps to make each invocation long enough to avoid timing artifacts. + * Performs a GC after re-creating the empty maps before every invocation, * so that only the GCs caused by the invocation contribute to the measurement. + * + * Records the memory used by all the maps in the last invocation of each iteration. */ @State(Scope.Thread) @AuxCounters @@ -28,24 +33,25 @@ private object OpenHashMapBenchmark { /** Minimum number of nanoseconds per invocation, so as to avoid timing artifacts. */ private[this] val minNanosPerInvocation = 1000000 // one millisecond - /** The minimum number of `put()` calls to make per invocation, so as to avoid timing artifacts. */ - private[this] val minPutsPerInvocation = minNanosPerInvocation / nanosPerPut - /** Size of the maps created in this trial. */ private[this] var size: Int = _ - /** Number of maps created in each invocation; the size of `maps`. */ - private[this] var n: Int = _ + /** Total number of entries in all of the `maps` combined. */ + var mapEntries: Int = _ /** Number of operations performed in the current invocation. */ var operations: Int = _ + /** Bytes of memory used in the object graphs of all the maps. */ + var memory: Long = _ + var maps: Array[OpenHashMap[Int,Int]] = null @Setup def threadSetup(params: BenchmarkParams) { size = params.getParam("size").toInt - n = math.ceil(minPutsPerInvocation / size).toInt + val n = math.ceil(minNanosPerInvocation / (nanosPerPut * size)).toInt + mapEntries = size * n maps = new Array(n) } @@ -56,10 +62,16 @@ private object OpenHashMapBenchmark { @Setup(Level.Invocation) def setup { - for (i <- 0 until n) maps(i) = new OpenHashMap[Int,Int](size) - operations += size * n + for (i <- 0 until maps.length) maps(i) = new OpenHashMap[Int,Int](size) + operations += mapEntries System.gc() // clean up after last invocation } + + @TearDown(Level.Iteration) + def iterationTeardown { + // limit to smaller cases to avoid OOM + memory = if (mapEntries <= 1000000) GraphLayout.parseInstance(maps(0), maps.tail).totalSize else 0 + } } /** State container for the `get()` bulk calling tests. From 2e8fb12f6d92e6021131461285b9c28909584d04 Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Sun, 27 Mar 2016 11:59:13 -0700 Subject: [PATCH 009/153] Add a JMH runner class to the library benchmark framework. --- test/benchmarks/README.md | 49 ++++++-- .../src/main/scala/benchmark/JmhRunner.scala | 16 +++ .../mutable/OpenHashMapRunner.scala | 111 ++++++++++++++++++ 3 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 test/benchmarks/src/main/scala/benchmark/JmhRunner.scala create mode 100644 test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md index aea72e90edf9..07e72f09a162 100644 --- a/test/benchmarks/README.md +++ b/test/benchmarks/README.md @@ -1,17 +1,48 @@ # Scala library benchmarks -This directory is a standalone SBT project -that makes use of the [SBT plugin for JMH](https://github.com/ktoso/sbt-jmh), -with the usual directory structure: -source code for the benchmarks, which utilize [JMH](http://openjdk.java.net/projects/code-tools/jmh/), -should be placed in `src/main/scala`. +This directory is a standalone SBT project, within the Scala project, +that makes use of the [SBT plugin](https://github.com/ktoso/sbt-jmh) for [JMH](http://openjdk.java.net/projects/code-tools/jmh/). -The benchmarks require first building Scala into `../../build/pack`. -They can then be (built and) run from `sbt` with "`jmh:run`". -"`jmh:run -h`" displays the usual JMH options available. +## running a benchmark + +The benchmarks require first building Scala into `../../build/pack`, using Ant. + +You'll then need to know the fully-qualified name of the benchmark runner class. +The benchmarking classes are organized under `src/main/scala`, +in the same package hierarchy as the classes that they test. +Assuming that we're benchmarking `scala.collection.mutable.OpenHashMap`, +the benchmark runner would likely be named `scala.collection.mutable.OpenHashMapRunner`. +Using this example, one would simply run + + jmh:runMain scala.collection.mutable.OpenHashMapRunner + +in SBT. +SBT should be run _from this directory_. + +The JMH results can be found under `target/jmh-results/`. +`target` gets deleted on an SBT `clean`, +so you should copy these files out of `target` if you wish to preserve them. + +## creating a benchmark and runner + +The benchmarking classes use the same package hierarchy as the classes that they test +in order to make it easy to expose, in package scope, members of the class under test, +should that be necessary for benchmarking. + +There are two types of classes in the source directory: +those suffixed "`Benchmark`" and those suffixed "`Runner`". +The former are benchmarks that can be run directly using `jmh:run`; +however, they are normally run from a corresponding class of the latter type, +which is run using `jmh:runMain` (as described above). +This …`Runner` class is useful for setting appropriate JMH command options, +and for processing the JMH results into files that can be read by other tools, such as Gnuplot. + +The `benchmark.JmhRunner` trait should be woven into any runner class, for the standard behavior that it provides. +This includes creating output files in a subdirectory of `target/jmh-results` +derived from the fully-qualified package name of the `Runner` class. ## some useful HotSpot options -Adding these to the `jmh:run` command line may help if you're using the HotSpot (Oracle, OpenJDK) compiler. +Adding these to the `jmh:run` or `jmh:runMain` command line may help if you're using the HotSpot (Oracle, OpenJDK) compiler. They require prefixing with `-jvmArgs`. See [the Java documentation](http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html) for more options. diff --git a/test/benchmarks/src/main/scala/benchmark/JmhRunner.scala b/test/benchmarks/src/main/scala/benchmark/JmhRunner.scala new file mode 100644 index 000000000000..cc75be529da2 --- /dev/null +++ b/test/benchmarks/src/main/scala/benchmark/JmhRunner.scala @@ -0,0 +1,16 @@ +package benchmark + +import java.io.File + +/** Common code for JMH runner objects. */ +trait JmhRunner { + private[this] val parentDirectory = new File("target", "jmh-results") + + /** Return the output directory for this class, creating the directory if necessary. */ + protected def outputDirectory: File = { + val subdir = getClass.getPackage.getName.replace('.', File.separatorChar) + val dir = new File(parentDirectory, subdir) + if (!dir.isDirectory) dir.mkdirs() + dir + } +} diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala new file mode 100644 index 000000000000..c139c55933b4 --- /dev/null +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala @@ -0,0 +1,111 @@ +package scala.collection.mutable + +import java.io.BufferedWriter +import java.io.File +import java.io.FileOutputStream +import java.io.OutputStreamWriter +import java.io.PrintWriter +import scala.collection.JavaConversions +import scala.language.existentials +import org.openjdk.jmh.results.RunResult +import org.openjdk.jmh.runner.Runner +import org.openjdk.jmh.runner.options.CommandLineOptions +import org.openjdk.jmh.runner.options.Options +import benchmark.JmhRunner +import org.openjdk.jmh.runner.options.OptionsBuilder +import org.openjdk.jmh.runner.options.VerboseMode + +/** Replacement JMH application that runs the [[OpenHashMap]] benchmark. + * + * Outputs the results in a form consumable by a Gnuplot script. + */ +object OpenHashMapRunner extends JmhRunner { + /** File that will be created for the output data set. */ + private[this] val outputFile = new File(outputDirectory, "OpenHashMap.dat") + + /** Qualifier to add to the name of a memory usage data set. */ + private[this] val memoryDatasetQualifer = " memory" + + /** Name of the JMH parameter for the number of map entries per invocation. */ + private[this] val sizeParamName = "size" + + /** Name of the JMH auxiliary counter that collects operation counts. */ + private[this] val operationsAuxCounterName = "operations" + + /** Name of the JMH auxiliary counter that collects memory usage. */ + private[this] val memoryAuxCounterName = "memory" + + /** Name of the JMH auxiliary counter that collects the number of map entries. */ + private[this] val entriesAuxCounterName = "mapEntries" + + def main(args: Array[String]) { + import scala.collection.JavaConversions._ + import scala.language.existentials + + val opts = new CommandLineOptions(args: _*) + var builder = new OptionsBuilder().parent(opts) + .jvmArgsPrepend("-Xmx6000m") + if (!opts.verbosity.hasValue) builder = builder.verbosity(VerboseMode.SILENT) + + val results = new Runner(builder.build).run() + + // Sort the results + + /** Map from data set name to data set. */ + val datasetByName = Map.empty[String, Set[RunResult]] + + /** Ordering for the results within a data set. Orders by increasing number of map entries. */ + val ordering = Ordering.by[RunResult, Int](_.getParams.getParam(sizeParamName).toInt) + + def addToDataset(result: RunResult, key: String): Unit = + datasetByName.get(key) + .getOrElse({ val d = SortedSet.empty(ordering); datasetByName.put(key, d); d }) += result + + results.foreach { result: RunResult ⇒ + addToDataset(result, result.getPrimaryResult.getLabel) + + // Create another data set for trials that track memory usage + if (result.getSecondaryResults.containsKey(memoryAuxCounterName)) + addToDataset(result, result.getPrimaryResult.getLabel + memoryDatasetQualifer) + } + + //TODO Write out test parameters + // val jvm = params.getJvm + // val jvmArgs = params.getJvmArgs.mkString(" ") + + val f = new PrintWriter(outputFile, "UTF-8") + try { + datasetByName.foreach(_ match { case (label: String, dataset: Iterable[RunResult]) ⇒ { + f.format("# [%s]\n", label) + + val isMemoryUsageDataset = label.contains(memoryDatasetQualifer) + dataset.foreach { result ⇒ + val size = result.getParams.getParam(sizeParamName) + val secondaryResults = result.getSecondaryResults + if (isMemoryUsageDataset) { + val memoryResult = secondaryResults.get(memoryAuxCounterName) + val entriesResult = secondaryResults.get(entriesAuxCounterName) + f.format("%s %f %f %f %f\n", size, + Double.box(entriesResult.getScore), Double.box(entriesResult.getStatistics.getStandardDeviation), + Double.box(memoryResult.getScore), Double.box(memoryResult.getStatistics.getStandardDeviation)) + } + else { + if (secondaryResults.containsKey(operationsAuxCounterName)) { + val operationsResult = secondaryResults.get(operationsAuxCounterName) + f.format("%s %f %f\n", size, + Double.box(operationsResult.getScore), Double.box(operationsResult.getStatistics.getStandardDeviation)) + } else { + val primary = result.getPrimaryResult + f.format("%s %f %f\n", size, + Double.box(primary.getScore), Double.box(primary.getStatistics.getStandardDeviation)) + } + } + } + + f.println(); f.println() // data set separator + }}) + } finally { + f.close() + } + } +} From cd7be12a35fd2cf7d0448d59b6f43e4165f43db4 Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Mon, 28 Mar 2016 13:54:43 -0700 Subject: [PATCH 010/153] Improve the OpenHashMapBenchmark run times. For the warm-up invocations, suppress setup and teardown that is only needed for the measurement iterations. Reduce the number of forks. --- .../mutable/OpenHashMapBenchmark.scala | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala index 13be9e6206f2..78e160a713c7 100644 --- a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala @@ -7,6 +7,8 @@ import org.openjdk.jmh.infra.BenchmarkParams import org.openjdk.jol.info.GraphLayout import org.openjdk.jol.info.GraphWalker import org.openjdk.jol.info.GraphVisitor +import org.openjdk.jmh.infra.IterationParams +import org.openjdk.jmh.runner.IterationType /** Utilities for the [[OpenHashMapBenchmark]]. * @@ -61,16 +63,21 @@ private object OpenHashMapBenchmark { } @Setup(Level.Invocation) - def setup { + def setup(params: IterationParams) { for (i <- 0 until maps.length) maps(i) = new OpenHashMap[Int,Int](size) - operations += mapEntries - System.gc() // clean up after last invocation + + if (params.getType == IterationType.MEASUREMENT) { + operations += mapEntries + System.gc() // clean up after last invocation + } } @TearDown(Level.Iteration) - def iterationTeardown { - // limit to smaller cases to avoid OOM - memory = if (mapEntries <= 1000000) GraphLayout.parseInstance(maps(0), maps.tail).totalSize else 0 + def iterationTeardown(params: IterationParams) { + if (params.getType == IterationType.MEASUREMENT) { + // limit to smaller cases to avoid OOM + memory = if (mapEntries <= 1000000) GraphLayout.parseInstance(maps(0), maps.tail).totalSize else 0 + } } } @@ -154,7 +161,7 @@ private object OpenHashMapBenchmark { /** Benchmark for the library's [[OpenHashMap]]. */ @BenchmarkMode(Array(Mode.AverageTime)) -@Fork(10) +@Fork(6) @Threads(1) @Warmup(iterations = 20) @Measurement(iterations = 6) From 00cbba19710b23f856f6c4a29e40a82a4ee364a9 Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Mon, 2 May 2016 22:47:58 -0700 Subject: [PATCH 011/153] Address JMH benchmark reviewer's issues. Besides tweaks to the documentation, this tests smaller (25-element) maps, and rewrites OpenHashMapRunner in more idiomatic Scala. --- test/benchmarks/README.md | 36 ++++---- .../mutable/OpenHashMapBenchmark.scala | 2 +- .../mutable/OpenHashMapRunner.scala | 82 +++++++++---------- 3 files changed, 61 insertions(+), 59 deletions(-) diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md index 07e72f09a162..370d610bc4ab 100644 --- a/test/benchmarks/README.md +++ b/test/benchmarks/README.md @@ -3,9 +3,11 @@ This directory is a standalone SBT project, within the Scala project, that makes use of the [SBT plugin](https://github.com/ktoso/sbt-jmh) for [JMH](http://openjdk.java.net/projects/code-tools/jmh/). -## running a benchmark +## Running a benchmark -The benchmarks require first building Scala into `../../build/pack`, using Ant. +The benchmarks require first building Scala into `../../build/pack` with `ant`. +If you want to build with `sbt dist/mkPack` instead, +you'll need to change `scalaHome` in this project. You'll then need to know the fully-qualified name of the benchmark runner class. The benchmarking classes are organized under `src/main/scala`, @@ -23,14 +25,14 @@ The JMH results can be found under `target/jmh-results/`. `target` gets deleted on an SBT `clean`, so you should copy these files out of `target` if you wish to preserve them. -## creating a benchmark and runner +## Creating a benchmark and runner The benchmarking classes use the same package hierarchy as the classes that they test in order to make it easy to expose, in package scope, members of the class under test, should that be necessary for benchmarking. There are two types of classes in the source directory: -those suffixed "`Benchmark`" and those suffixed "`Runner`". +those suffixed `Benchmark` and those suffixed `Runner`. The former are benchmarks that can be run directly using `jmh:run`; however, they are normally run from a corresponding class of the latter type, which is run using `jmh:runMain` (as described above). @@ -41,39 +43,45 @@ The `benchmark.JmhRunner` trait should be woven into any runner class, for the s This includes creating output files in a subdirectory of `target/jmh-results` derived from the fully-qualified package name of the `Runner` class. -## some useful HotSpot options +## Some useful HotSpot options Adding these to the `jmh:run` or `jmh:runMain` command line may help if you're using the HotSpot (Oracle, OpenJDK) compiler. They require prefixing with `-jvmArgs`. See [the Java documentation](http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html) for more options. -### viewing JIT compilation events +### Viewing JIT compilation events Adding `-XX:+PrintCompilation` shows when Java methods are being compiled or deoptimized. At the most basic level, these messages will tell you whether the code that you're measuring is still being tuned, so that you know whether you're running enough warm-up iterations. See [Kris Mok's notes](https://gist.github.com/rednaxelafx/1165804#file-notes-md) to interpret the output in detail. -### consider GC events +### Consider GC events If you're not explicitly performing `System.gc()` calls outside of your benchmarking code, you should add the JVM option `-verbose:gc` to understand the effect that GCs may be having on your tests. -### "diagnostic" options +### "Diagnostic" options These require the `-XX:+UnlockDiagnosticVMOptions` JVM option. -#### viewing inlining events +#### Viewing inlining events Add `-XX:+PrintInlining`. -#### viewing the disassembled code +#### Viewing the disassembled code +If you're running OpenJDK or Oracle JVM, +you may need to install the disassembler library (`hsdis-amd64.so` for the `amd64` architecture). +In Debian, this is available in +the `libhsdis0-fcml` package. +For an Oracle (or other compatible) JVM not set up by your distribution, +you may also need to copy or link the disassembler library +to the `jre/lib/`_`architecture`_ directory inside your JVM installation directory. + To show the assembly code corresponding to the code generated by the JIT compiler for specific methods, add `-XX:CompileCommand=print,scala.collection.mutable.OpenHashMap::*`, for example, to show all of the methods in the `scala.collection.mutable.OpenHashMap` class. -If you're running OpenJDK, you may need to install the disassembler library (`hsdis-amd64.so` for the `amd64` architecture). -In Debian, this is available in the `libhsdis0-fcml` package. To show it for _all_ methods, add `-XX:+PrintAssembly`. (This is usually excessive.) -## useful reading +## Useful reading * [OpenJDK advice on microbenchmarks](https://wiki.openjdk.java.net/display/HotSpot/MicroBenchmarks) * Brian Goetz's "Java theory and practice" articles: * "[Dynamic compilation and performance measurement](http://www.ibm.com/developerworks/java/library/j-jtp12214/)" @@ -81,7 +89,7 @@ To show it for _all_ methods, add `-XX:+PrintAssembly`. * [Doug Lea's JSR 166 benchmarks](http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/loops/) * "[Measuring performance](http://docs.scala-lang.org/overviews/parallel-collections/performance.html)" of Scala parallel collections -## legacy frameworks +## Legacy frameworks An older version of the benchmarking framework is still present in this directory, in the following locations: diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala index 78e160a713c7..26e26b30654a 100644 --- a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala @@ -170,7 +170,7 @@ private object OpenHashMapBenchmark { class OpenHashMapBenchmark { import OpenHashMapBenchmark._ - @Param(Array("50", "100", "250", "1000", "2500", "10000", "25000", "100000", "250000", "1000000", "2500000", + @Param(Array("25", "50", "100", "250", "1000", "2500", "10000", "25000", "100000", "250000", "1000000", "2500000", "5000000", "7500000", "10000000", "25000000")) var size: Int = _ diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala index c139c55933b4..1a58b18ee979 100644 --- a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala @@ -14,6 +14,7 @@ import org.openjdk.jmh.runner.options.Options import benchmark.JmhRunner import org.openjdk.jmh.runner.options.OptionsBuilder import org.openjdk.jmh.runner.options.VerboseMode +import org.openjdk.jmh.results.Result /** Replacement JMH application that runs the [[OpenHashMap]] benchmark. * @@ -24,27 +25,35 @@ object OpenHashMapRunner extends JmhRunner { private[this] val outputFile = new File(outputDirectory, "OpenHashMap.dat") /** Qualifier to add to the name of a memory usage data set. */ - private[this] val memoryDatasetQualifer = " memory" + private[this] val memoryDatasetQualifier = "-memory" - /** Name of the JMH parameter for the number of map entries per invocation. */ - private[this] val sizeParamName = "size" + private[this] implicit class MyRunResult(r: RunResult) { + /** Return the dataset label. */ + def label = r.getPrimaryResult.getLabel - /** Name of the JMH auxiliary counter that collects operation counts. */ - private[this] val operationsAuxCounterName = "operations" + /** Return the value of the JMH parameter for the number of map entries per invocation. */ + def size: String = r.getParams.getParam("size") - /** Name of the JMH auxiliary counter that collects memory usage. */ - private[this] val memoryAuxCounterName = "memory" + /** Return the operation counts. */ + def operations = Option(r.getSecondaryResults.get("operations")) + + /** Return the number of map entries. */ + def entries = r.getSecondaryResults.get("mapEntries") + + /** Return the memory usage. */ + def memory = Option(r.getSecondaryResults.get("memory")) + } + + /** Return the statistics of the given result as a string. */ + private[this] def stats(r: Result[_]) = r.getScore + " " + r.getStatistics.getStandardDeviation - /** Name of the JMH auxiliary counter that collects the number of map entries. */ - private[this] val entriesAuxCounterName = "mapEntries" def main(args: Array[String]) { import scala.collection.JavaConversions._ import scala.language.existentials val opts = new CommandLineOptions(args: _*) - var builder = new OptionsBuilder().parent(opts) - .jvmArgsPrepend("-Xmx6000m") + var builder = new OptionsBuilder().parent(opts).jvmArgsPrepend("-Xmx6000m") if (!opts.verbosity.hasValue) builder = builder.verbosity(VerboseMode.SILENT) val results = new Runner(builder.build).run() @@ -55,18 +64,17 @@ object OpenHashMapRunner extends JmhRunner { val datasetByName = Map.empty[String, Set[RunResult]] /** Ordering for the results within a data set. Orders by increasing number of map entries. */ - val ordering = Ordering.by[RunResult, Int](_.getParams.getParam(sizeParamName).toInt) + val ordering = Ordering.by[RunResult, Int](_.size.toInt) - def addToDataset(result: RunResult, key: String): Unit = - datasetByName.get(key) - .getOrElse({ val d = SortedSet.empty(ordering); datasetByName.put(key, d); d }) += result + def addToDataset(key: String, result: RunResult): Unit = + datasetByName.getOrElseUpdate(key, SortedSet.empty(ordering)) += result - results.foreach { result: RunResult ⇒ - addToDataset(result, result.getPrimaryResult.getLabel) + results.foreach { result => + addToDataset(result.label, result) // Create another data set for trials that track memory usage - if (result.getSecondaryResults.containsKey(memoryAuxCounterName)) - addToDataset(result, result.getPrimaryResult.getLabel + memoryDatasetQualifer) + if (result.memory.isDefined) + addToDataset(result.label + memoryDatasetQualifier, result) } //TODO Write out test parameters @@ -75,31 +83,17 @@ object OpenHashMapRunner extends JmhRunner { val f = new PrintWriter(outputFile, "UTF-8") try { - datasetByName.foreach(_ match { case (label: String, dataset: Iterable[RunResult]) ⇒ { - f.format("# [%s]\n", label) - - val isMemoryUsageDataset = label.contains(memoryDatasetQualifer) - dataset.foreach { result ⇒ - val size = result.getParams.getParam(sizeParamName) - val secondaryResults = result.getSecondaryResults - if (isMemoryUsageDataset) { - val memoryResult = secondaryResults.get(memoryAuxCounterName) - val entriesResult = secondaryResults.get(entriesAuxCounterName) - f.format("%s %f %f %f %f\n", size, - Double.box(entriesResult.getScore), Double.box(entriesResult.getStatistics.getStandardDeviation), - Double.box(memoryResult.getScore), Double.box(memoryResult.getStatistics.getStandardDeviation)) - } - else { - if (secondaryResults.containsKey(operationsAuxCounterName)) { - val operationsResult = secondaryResults.get(operationsAuxCounterName) - f.format("%s %f %f\n", size, - Double.box(operationsResult.getScore), Double.box(operationsResult.getStatistics.getStandardDeviation)) - } else { - val primary = result.getPrimaryResult - f.format("%s %f %f\n", size, - Double.box(primary.getScore), Double.box(primary.getStatistics.getStandardDeviation)) - } - } + datasetByName.foreach(_ match { case (label: String, dataset: Iterable[RunResult]) => { + f.println(s"# [$label]") + + val isMemoryUsageDataset = label.endsWith(memoryDatasetQualifier) + dataset.foreach { r => + f.println(r.size + " " + ( + if (isMemoryUsageDataset) + stats(r.entries) + " " + stats(r.memory.get) + else + stats(r.operations getOrElse r.getPrimaryResult) + )) } f.println(); f.println() // data set separator From 486821b845ccaa0d02dd402fb3532d6d82055015 Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Tue, 3 May 2016 10:52:28 -0700 Subject: [PATCH 012/153] Enable full compiler optimizations in JMH benchmarking. --- test/benchmarks/build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/build.sbt b/test/benchmarks/build.sbt index 2959e4986ad2..4806ecdde80c 100644 --- a/test/benchmarks/build.sbt +++ b/test/benchmarks/build.sbt @@ -1,6 +1,6 @@ scalaHome := Some(file("../../build/pack")) scalaVersion := "2.11.8" -scalacOptions += "-feature" +scalacOptions ++= Seq("-feature", "-Yopt:l:classpath") lazy val root = (project in file(".")). enablePlugins(JmhPlugin). From 5faad77ccebb41e9674b103d499de927c0dba662 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Fri, 6 May 2016 12:39:13 +0100 Subject: [PATCH 013/153] Added pos test with multiple cases; added neg tests. --- test/files/neg/hkgadt.check | 31 +++++++++++++++++++++++++++++++ test/files/neg/hkgadt.scala | 35 +++++++++++++++++++++++++++++++++++ test/files/pos/hkgadt.scala | 25 +++++++++++++++++++++---- 3 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 test/files/neg/hkgadt.check create mode 100644 test/files/neg/hkgadt.scala diff --git a/test/files/neg/hkgadt.check b/test/files/neg/hkgadt.check new file mode 100644 index 000000000000..ef302a9abf38 --- /dev/null +++ b/test/files/neg/hkgadt.check @@ -0,0 +1,31 @@ +hkgadt.scala:7: error: type mismatch; + found : scala.collection.immutable.Set[Int] + required: F[Int] + case Bar() => Set(1) + ^ +hkgadt.scala:13: error: type mismatch; + found : Boolean(true) + required: A + case Bar1() => true + ^ +hkgadt.scala:24: error: type mismatch; + found : scala.collection.immutable.Set[Int] + required: F[Int] + case Bar() => Set(1) + ^ +hkgadt.scala:25: error: type mismatch; + found : List[Int] + required: F[Int] + case Baz() => List(1) + ^ +hkgadt.scala:32: error: type mismatch; + found : Boolean(true) + required: A + case Bar1() => true + ^ +hkgadt.scala:33: error: type mismatch; + found : Int(1) + required: A + case Baz1() => 1 + ^ +6 errors found diff --git a/test/files/neg/hkgadt.scala b/test/files/neg/hkgadt.scala new file mode 100644 index 000000000000..0107d2bdde31 --- /dev/null +++ b/test/files/neg/hkgadt.scala @@ -0,0 +1,35 @@ +object HKGADT { + sealed trait Foo[F[_]] + final case class Bar() extends Foo[List] + + def frob[F[_]](foo: Foo[F]): F[Int] = + foo match { + case Bar() => Set(1) + } + + sealed trait Foo1[F] + final case class Bar1() extends Foo1[Int] + def frob1[A](foo: Foo1[A]): A = foo match { + case Bar1() => true + } +} + +object HKGADT2 { + sealed trait Foo[F[_]] + final case class Bar() extends Foo[List] + final case class Baz() extends Foo[Set] + + def frob[F[_]](foo: Foo[F]): F[Int] = + foo match { + case Bar() => Set(1) + case Baz() => List(1) + } + + sealed trait Foo1[F] + final case class Bar1() extends Foo1[Int] + final case class Baz1() extends Foo1[Boolean] + def frob1[A](foo: Foo1[A]): A = foo match { + case Bar1() => true + case Baz1() => 1 + } +} diff --git a/test/files/pos/hkgadt.scala b/test/files/pos/hkgadt.scala index 0f3739f4d400..5719c752cdef 100644 --- a/test/files/pos/hkgadt.scala +++ b/test/files/pos/hkgadt.scala @@ -1,18 +1,35 @@ -package test - object HKGADT { sealed trait Foo[F[_]] final case class Bar() extends Foo[List] def frob[F[_]](foo: Foo[F]): F[Int] = foo match { - case Bar() => - List(1) + case Bar() => List(1) + } + + sealed trait Foo1[F] + final case class Bar1() extends Foo1[Int] + def frob1[A](foo: Foo1[A]): A = foo match { + case Bar1() => 1 + } +} + +object HKGADT2 { + sealed trait Foo[F[_]] + final case class Bar() extends Foo[List] + final case class Baz() extends Foo[Set] + + def frob[F[_]](foo: Foo[F]): F[Int] = + foo match { + case Bar() => List(1) + case Baz() => Set(1) } sealed trait Foo1[F] final case class Bar1() extends Foo1[Int] + final case class Baz1() extends Foo1[Boolean] def frob1[A](foo: Foo1[A]): A = foo match { case Bar1() => 1 + case Baz1() => true } } From b58634e9f95625a44c427d352d580ed99b3f28da Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 5 Apr 2016 11:45:53 +0200 Subject: [PATCH 014/153] Improves the test cases for the scala-concurrent-tck --- test/files/jvm/scala-concurrent-tck.check | 2 +- test/files/jvm/scala-concurrent-tck.scala | 31 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/test/files/jvm/scala-concurrent-tck.check b/test/files/jvm/scala-concurrent-tck.check index 9aef07d1e54a..8aec46e5d636 100644 --- a/test/files/jvm/scala-concurrent-tck.check +++ b/test/files/jvm/scala-concurrent-tck.check @@ -1 +1 @@ -warning: there were 73 deprecation warnings; re-run with -deprecation for details +warning: there were 75 deprecation warnings; re-run with -deprecation for details diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala index 8069028cf51f..7197c1d85394 100644 --- a/test/files/jvm/scala-concurrent-tck.scala +++ b/test/files/jvm/scala-concurrent-tck.scala @@ -90,6 +90,25 @@ trait FutureCallbacks extends TestBase { promise.success(-1) } + def stressTestNumberofCallbacks(): Unit = once { + done => + val promise = Promise[Unit] + val otherPromise = Promise[Unit] + def attachMeaninglessCallbacksTo(f: Future[Any]): Unit = (1 to 1000).foreach(_ => f.onComplete(_ => ())) + attachMeaninglessCallbacksTo(promise.future) + val future = promise.future.flatMap { _ => + attachMeaninglessCallbacksTo(otherPromise.future) + otherPromise.future + } + val numbers = new java.util.concurrent.ConcurrentHashMap[Int, Unit]() + (0 to 10000) foreach { x => numbers.put(x, ()) } + Future.sequence((0 to 10000) map { x => future.andThen({ case _ => numbers.remove(x) }) }) onComplete { + _ => done(numbers.isEmpty) + } + promise.success(()) + otherPromise.success(()) + } + testOnSuccess() testOnSuccessWhenCompleted() testOnSuccessWhenFailed() @@ -100,6 +119,7 @@ trait FutureCallbacks extends TestBase { //testOnFailureWhenSpecialThrowable(7, new InterruptedException) testThatNestedCallbacksDoNotYieldStackOverflow() testOnFailureWhenTimeoutException() + stressTestNumberofCallbacks() } @@ -283,6 +303,16 @@ def testTransformFailure(): Unit = once { g onFailure { case t => done(t.getMessage() == "expected") } } + def testFlatMapDelayed(): Unit = once { + done => + val f = Future { 5 } + val p = Promise[Int] + val g = f flatMap { _ => p.future } + g onSuccess { case x => done(x == 10) } + g onFailure { case _ => done(false) } + p.success(10) + } + def testFilterSuccess(): Unit = once { done => val f = Future { 4 } @@ -458,6 +488,7 @@ def testTransformFailure(): Unit = once { testMapFailure() testFlatMapSuccess() testFlatMapFailure() + testFlatMapDelayed() testFilterSuccess() testFilterFailure() testCollectSuccess() From a6d5eb507bbeac2055a224a15fd76e7f9425520b Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 4 May 2016 15:52:01 -0700 Subject: [PATCH 015/153] SI-8667 Improve too-many-args message Use removeNames to help diagnose the application. Supplement the error message with how many extra args and any other residual assignments that the user might have thought was a properly named arg. The error message is gradual: succinct for short arg lists, more verbose for longer applications. Very long arg lists are probably generated, so that message is the least colloquial. --- .../tools/nsc/typechecker/ContextErrors.scala | 31 +++++++- .../scala/tools/nsc/typechecker/Typers.scala | 10 ++- test/files/neg/eta-expand-star.check | 2 +- .../neg/macro-invalidusage-badargs.check | 2 +- test/files/neg/multi-array.check | 2 +- test/files/neg/protected-constructors.check | 2 +- test/files/neg/t1112.check | 2 +- test/files/neg/t1523.check | 2 +- test/files/neg/t6920.check | 2 +- test/files/neg/t7157.check | 24 +++--- test/files/neg/t8006.check | 2 +- test/files/neg/t8035-no-adapted-args.check | 2 +- test/files/neg/t8667.check | 79 +++++++++++++++++++ test/files/neg/t8667.scala | 35 ++++++++ test/files/neg/t876.check | 2 +- 15 files changed, 172 insertions(+), 27 deletions(-) create mode 100644 test/files/neg/t8667.check create mode 100644 test/files/neg/t8667.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index e190b57017b7..e1055144f8c7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -538,8 +538,33 @@ trait ContextErrors { def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) = NormalTypeError(tree, "macro applications do not support named and/or default arguments") - def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) = - NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun)) + def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree, expected: Int, supplied: Int, unknowns: List[Name]) = { + val msg = { + val badappl = { + val excess = supplied - expected + val target = treeSymTypeMsg(fun) + + if (expected == 0) s"no arguments allowed for nullary $target" + else if (excess < 3 && expected <= 5) s"too many arguments ($supplied) for $target" + else if (expected > 10) s"$supplied arguments but expected $expected for $target" + else { + val oneOf = + if (excess == 1) "one more argument" + else if (excess > 0) s"$excess more arguments" + else "too many arguments" + s"$oneOf than can be applied to $target" + } + } + val suppl = + unknowns.size match { + case 0 => "" + case 1 => s"\nNote that '${unknowns.head}' is not a parameter name of the invoked method." + case _ => unknowns.mkString("\nNote that '", "', '", "' are not parameter names of the invoked method.") + } + s"${badappl}${suppl}" + } + NormalTypeError(tree, msg) + } // can it still happen? see test case neg/overloaded-unapply.scala def OverloadedUnapplyError(tree: Tree) = @@ -551,7 +576,7 @@ trait ContextErrors { def MultipleVarargError(tree: Tree) = NormalTypeError(tree, "when using named arguments, the vararg parameter has to be specified exactly once") - def ModuleUsingCompanionClassDefaultArgsErrror(tree: Tree) = + def ModuleUsingCompanionClassDefaultArgsError(tree: Tree) = NormalTypeError(tree, "module extending its companion class cannot use default constructor arguments") def NotEnoughArgsError(tree: Tree, fun: Tree, missing: List[Symbol]) = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 329ce8c23b46..1d24d8c232c0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3330,7 +3330,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // #2064 duplErrorTree(WrongNumberOfArgsError(tree, fun)) } else if (lencmp > 0) { - tryTupleApply orElse duplErrorTree(TooManyArgsNamesDefaultsError(tree, fun)) + tryTupleApply orElse duplErrorTree { + val (namelessArgs, _) = removeNames(Typer.this)(args, params) + val wrongs = (namelessArgs zip args) collect { + case (_: Assign, AssignOrNamedArg(Ident(name), _)) => name + } + TooManyArgsNamesDefaultsError(tree, fun, expected = formals.size, supplied = args.size, wrongs) + } } else if (lencmp == 0) { // we don't need defaults. names were used, so this application is transformed // into a block (@see transformNamedApplication in NamesDefaults) @@ -3394,7 +3400,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val lencmp2 = compareLengths(allArgs, formals) if (!sameLength(allArgs, args) && callToCompanionConstr(context, funSym)) { - duplErrorTree(ModuleUsingCompanionClassDefaultArgsErrror(tree)) + duplErrorTree(ModuleUsingCompanionClassDefaultArgsError(tree)) } else if (lencmp2 > 0) { removeNames(Typer.this)(allArgs, params) // #3818 duplErrTree diff --git a/test/files/neg/eta-expand-star.check b/test/files/neg/eta-expand-star.check index 6765d504fc55..f25e0a41ffad 100644 --- a/test/files/neg/eta-expand-star.check +++ b/test/files/neg/eta-expand-star.check @@ -1,4 +1,4 @@ -eta-expand-star.scala:6: error: too many arguments for method apply: (v1: Seq[T])Unit in trait Function1 +eta-expand-star.scala:6: error: too many arguments (2) for method apply: (v1: Seq[T])Unit in trait Function1 g(1, 2) ^ one error found diff --git a/test/files/neg/macro-invalidusage-badargs.check b/test/files/neg/macro-invalidusage-badargs.check index 19ac6528d37d..2f5f6d106423 100644 --- a/test/files/neg/macro-invalidusage-badargs.check +++ b/test/files/neg/macro-invalidusage-badargs.check @@ -13,7 +13,7 @@ Macros_Test_2.scala:8: error: not enough arguments for macro method foo: (x: Int Unspecified value parameter x. foo() ^ -Macros_Test_2.scala:9: error: too many arguments for macro method foo: (x: Int)Int +Macros_Test_2.scala:9: error: too many arguments (2) for macro method foo: (x: Int)Int foo(4, 2) ^ 5 errors found diff --git a/test/files/neg/multi-array.check b/test/files/neg/multi-array.check index 511caa126fc0..a71f9b864af4 100644 --- a/test/files/neg/multi-array.check +++ b/test/files/neg/multi-array.check @@ -1,4 +1,4 @@ -multi-array.scala:7: error: too many arguments for constructor Array: (_length: Int)Array[T] +multi-array.scala:7: error: too many arguments (2) for constructor Array: (_length: Int)Array[T] val a: Array[Int] = new Array(10, 10) ^ one error found diff --git a/test/files/neg/protected-constructors.check b/test/files/neg/protected-constructors.check index f44d7db9b982..5c880cb67206 100644 --- a/test/files/neg/protected-constructors.check +++ b/test/files/neg/protected-constructors.check @@ -1,4 +1,4 @@ -protected-constructors.scala:17: error: too many arguments for constructor Foo1: ()dingus.Foo1 +protected-constructors.scala:17: error: no arguments allowed for nullary constructor Foo1: ()dingus.Foo1 val foo1 = new Foo1("abc") ^ protected-constructors.scala:18: error: constructor Foo2 in class Foo2 cannot be accessed in object P diff --git a/test/files/neg/t1112.check b/test/files/neg/t1112.check index 5e3821b1535f..9c1254d17655 100644 --- a/test/files/neg/t1112.check +++ b/test/files/neg/t1112.check @@ -1,4 +1,4 @@ -t1112.scala:12: error: too many arguments for method call: (p: Int)(f: => Test.this.Type1)Unit +t1112.scala:12: error: too many arguments (2) for method call: (p: Int)(f: => Test.this.Type1)Unit call(0,() => System.out.println("here we are")) ^ one error found diff --git a/test/files/neg/t1523.check b/test/files/neg/t1523.check index d2489f2602a6..656845a4578d 100644 --- a/test/files/neg/t1523.check +++ b/test/files/neg/t1523.check @@ -1,4 +1,4 @@ -t1523.scala:4: error: too many arguments for method bug: (x: Any)Any +t1523.scala:4: error: 25 more arguments than can be applied to method bug: (x: Any)Any def go() = bug("a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a") ^ one error found diff --git a/test/files/neg/t6920.check b/test/files/neg/t6920.check index ee4eafb83ec3..4e33aca3bc9a 100644 --- a/test/files/neg/t6920.check +++ b/test/files/neg/t6920.check @@ -1,4 +1,4 @@ -t6920.scala:9: error: too many arguments for method applyDynamicNamed: (values: Seq[(String, Any)])String +t6920.scala:9: error: too many arguments (2) for method applyDynamicNamed: (values: Seq[(String, Any)])String error after rewriting to CompilerError.this.test.applyDynamicNamed("crushTheCompiler")(scala.Tuple2("a", 1), scala.Tuple2("b", 2)) possible cause: maybe a wrong Dynamic method signature? test.crushTheCompiler(a = 1, b = 2) diff --git a/test/files/neg/t7157.check b/test/files/neg/t7157.check index 3988460d4bb5..a043c5d40370 100644 --- a/test/files/neg/t7157.check +++ b/test/files/neg/t7157.check @@ -1,20 +1,20 @@ -Test_2.scala:5: error: too many arguments for macro method m1_0_0: ()Unit +Test_2.scala:5: error: no arguments allowed for nullary macro method m1_0_0: ()Unit m1_0_0(1) ^ -Test_2.scala:6: error: too many arguments for macro method m1_0_0: ()Unit +Test_2.scala:6: error: no arguments allowed for nullary macro method m1_0_0: ()Unit m1_0_0(1, 2) ^ -Test_2.scala:7: error: too many arguments for macro method m1_0_0: ()Unit +Test_2.scala:7: error: no arguments allowed for nullary macro method m1_0_0: ()Unit m1_0_0(1, 2, 3) ^ Test_2.scala:9: error: not enough arguments for macro method m1_1_1: (x: Int)Unit. Unspecified value parameter x. m1_1_1() ^ -Test_2.scala:11: error: too many arguments for macro method m1_1_1: (x: Int)Unit +Test_2.scala:11: error: too many arguments (2) for macro method m1_1_1: (x: Int)Unit m1_1_1(1, 2) ^ -Test_2.scala:12: error: too many arguments for macro method m1_1_1: (x: Int)Unit +Test_2.scala:12: error: too many arguments (3) for macro method m1_1_1: (x: Int)Unit m1_1_1(1, 2, 3) ^ Test_2.scala:14: error: not enough arguments for macro method m1_2_2: (x: Int, y: Int)Unit. @@ -25,7 +25,7 @@ Test_2.scala:15: error: not enough arguments for macro method m1_2_2: (x: Int, y Unspecified value parameter y. m1_2_2(1) ^ -Test_2.scala:17: error: too many arguments for macro method m1_2_2: (x: Int, y: Int)Unit +Test_2.scala:17: error: too many arguments (3) for macro method m1_2_2: (x: Int, y: Int)Unit m1_2_2(1, 2, 3) ^ Test_2.scala:24: error: not enough arguments for macro method m1_1_inf: (x: Int, y: Int*)Unit. @@ -40,23 +40,23 @@ Test_2.scala:30: error: not enough arguments for macro method m1_2_inf: (x: Int, Unspecified value parameters y, z. m1_2_inf(1) ^ -Test_2.scala:35: error: too many arguments for macro method m2_0_0: ()Unit +Test_2.scala:35: error: no arguments allowed for nullary macro method m2_0_0: ()Unit m2_0_0()(1) ^ -Test_2.scala:36: error: too many arguments for macro method m2_0_0: ()Unit +Test_2.scala:36: error: no arguments allowed for nullary macro method m2_0_0: ()Unit m2_0_0()(1, 2) ^ -Test_2.scala:37: error: too many arguments for macro method m2_0_0: ()Unit +Test_2.scala:37: error: no arguments allowed for nullary macro method m2_0_0: ()Unit m2_0_0()(1, 2, 3) ^ Test_2.scala:39: error: not enough arguments for macro method m2_1_1: (x: Int)Unit. Unspecified value parameter x. m2_1_1()() ^ -Test_2.scala:41: error: too many arguments for macro method m2_1_1: (x: Int)Unit +Test_2.scala:41: error: too many arguments (2) for macro method m2_1_1: (x: Int)Unit m2_1_1()(1, 2) ^ -Test_2.scala:42: error: too many arguments for macro method m2_1_1: (x: Int)Unit +Test_2.scala:42: error: too many arguments (3) for macro method m2_1_1: (x: Int)Unit m2_1_1()(1, 2, 3) ^ Test_2.scala:44: error: not enough arguments for macro method m2_2_2: (x: Int, y: Int)Unit. @@ -67,7 +67,7 @@ Test_2.scala:45: error: not enough arguments for macro method m2_2_2: (x: Int, y Unspecified value parameter y. m2_2_2()(1) ^ -Test_2.scala:47: error: too many arguments for macro method m2_2_2: (x: Int, y: Int)Unit +Test_2.scala:47: error: too many arguments (3) for macro method m2_2_2: (x: Int, y: Int)Unit m2_2_2()(1, 2, 3) ^ Test_2.scala:54: error: not enough arguments for macro method m2_1_inf: (x: Int, y: Int*)Unit. diff --git a/test/files/neg/t8006.check b/test/files/neg/t8006.check index fbac26e3ad9c..4e130670e4d4 100644 --- a/test/files/neg/t8006.check +++ b/test/files/neg/t8006.check @@ -1,4 +1,4 @@ -t8006.scala:3: error: too many arguments for method applyDynamicNamed: (value: (String, Any))String +t8006.scala:3: error: too many arguments (2) for method applyDynamicNamed: (value: (String, Any))String error after rewriting to X.this.d.applyDynamicNamed("meth")(scala.Tuple2("value1", 10), scala.Tuple2("value2", 100)) possible cause: maybe a wrong Dynamic method signature? d.meth(value1 = 10, value2 = 100) // two arguments here, but only one is allowed diff --git a/test/files/neg/t8035-no-adapted-args.check b/test/files/neg/t8035-no-adapted-args.check index 43637b2c1fc2..4b3cb39c769f 100644 --- a/test/files/neg/t8035-no-adapted-args.check +++ b/test/files/neg/t8035-no-adapted-args.check @@ -4,7 +4,7 @@ t8035-no-adapted-args.scala:4: warning: No automatic adaptation here: use explic after adaptation: Test.f((1, 2, 3): (Int, Int, Int)) f(1, 2, 3) ^ -t8035-no-adapted-args.scala:4: error: too many arguments for method f: (x: (Int, Int, Int))Int +t8035-no-adapted-args.scala:4: error: too many arguments (3) for method f: (x: (Int, Int, Int))Int f(1, 2, 3) ^ t8035-no-adapted-args.scala:5: warning: No automatic adaptation here: use explicit parentheses. diff --git a/test/files/neg/t8667.check b/test/files/neg/t8667.check new file mode 100644 index 000000000000..4c3bcb78c829 --- /dev/null +++ b/test/files/neg/t8667.check @@ -0,0 +1,79 @@ +t8667.scala:6: error: too many arguments (3) for constructor C: (a: Int, b: Int)C +Note that 'c' is not a parameter name of the invoked method. + def c2 = new C(a = 42, b = 17, c = 5) + ^ +t8667.scala:7: error: unknown parameter name: c + def c3 = new C(b = 42, a = 17, c = 5) + ^ +t8667.scala:7: error: too many arguments (3) for constructor C: (a: Int, b: Int)C + def c3 = new C(b = 42, a = 17, c = 5) + ^ +t8667.scala:8: error: positional after named argument. + def c4 = new C(b = 42, a = 17, 5) + ^ +t8667.scala:8: error: too many arguments (3) for constructor C: (a: Int, b: Int)C + def c4 = new C(b = 42, a = 17, 5) + ^ +t8667.scala:9: error: not found: value c + def c5 = new C(a = 42, c = 17) + ^ +t8667.scala:10: error: parameter 'b' is already specified at parameter position 2 +Note that 'c' is not a parameter name of the invoked method. + def c6 = new C(a = 42, c = 17, b = 5) + ^ +t8667.scala:10: error: too many arguments (3) for constructor C: (a: Int, b: Int)C +Note that 'c' is not a parameter name of the invoked method. + def c6 = new C(a = 42, c = 17, b = 5) + ^ +t8667.scala:11: error: too many arguments (3) for constructor C: (a: Int, b: Int)C +Note that 'c' is not a parameter name of the invoked method. + def c7 = new C(42, 17, c = 5) + ^ +t8667.scala:12: error: parameter 'b' is already specified at parameter position 2 + def c8 = new C(42, 17, b = 5) + ^ +t8667.scala:12: error: too many arguments (3) for constructor C: (a: Int, b: Int)C + def c8 = new C(42, 17, b = 5) + ^ +t8667.scala:13: error: parameter 'b' is already specified at parameter position 2 +Note that 'c' is not a parameter name of the invoked method. + def c9 = new C(a = 42, c = 17, d = 3, b = 5) + ^ +t8667.scala:13: error: too many arguments (4) for constructor C: (a: Int, b: Int)C +Note that 'c', 'd' are not parameter names of the invoked method. + def c9 = new C(a = 42, c = 17, d = 3, b = 5) + ^ +t8667.scala:14: error: too many arguments (4) for constructor C: (a: Int, b: Int)C +Note that 'd', 'c' are not parameter names of the invoked method. + def c0 = new C(42, 17, d = 3, c = 5) + ^ +t8667.scala:24: error: no arguments allowed for nullary method f0: ()Int + f0(1) + ^ +t8667.scala:25: error: too many arguments (2) for method f1: (i: Int)Int + f1(1, 2) + ^ +t8667.scala:26: error: too many arguments (3) for method f1: (i: Int)Int + f1(1, 2, 3) + ^ +t8667.scala:27: error: 3 more arguments than can be applied to method f1: (i: Int)Int + f1(1, 2, 3, 4) + ^ +t8667.scala:28: error: 3 more arguments than can be applied to method f1: (i: Int)Int +Note that 'j' is not a parameter name of the invoked method. + f1(1, j = 2, 3, 4) + ^ +t8667.scala:29: error: 3 more arguments than can be applied to method f1: (i: Int)Int +Note that 'j', 'k' are not parameter names of the invoked method. + f1(1, j = 2, k = 3, 4) + ^ +t8667.scala:30: error: one more argument than can be applied to method f6: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int)Int + f6(1, 2, 3, 4, 5, 6, 7) + ^ +t8667.scala:31: error: 2 more arguments than can be applied to method f6: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int)Int + f6(1, 2, 3, 4, 5, 6, 7, 8) + ^ +t8667.scala:32: error: 15 arguments but expected 12 for method f12: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int, s: Int, t: Int)Int + f12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) + ^ +23 errors found diff --git a/test/files/neg/t8667.scala b/test/files/neg/t8667.scala new file mode 100644 index 000000000000..fe17eac84f6c --- /dev/null +++ b/test/files/neg/t8667.scala @@ -0,0 +1,35 @@ + +class C(a: Int, b: Int) + +trait T { + def c1 = new C(a = 42, b = 17) + def c2 = new C(a = 42, b = 17, c = 5) + def c3 = new C(b = 42, a = 17, c = 5) + def c4 = new C(b = 42, a = 17, 5) + def c5 = new C(a = 42, c = 17) + def c6 = new C(a = 42, c = 17, b = 5) + def c7 = new C(42, 17, c = 5) + def c8 = new C(42, 17, b = 5) + def c9 = new C(a = 42, c = 17, d = 3, b = 5) + def c0 = new C(42, 17, d = 3, c = 5) +} + +trait X { + def f0() = 42 + def f1(i: Int) = 42 + def f6(i: Int, j: Int, k: Int, l: Int, m: Int, n: Int) = 42 + def f12(i: Int, j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int, s: Int, t: Int) = 42 + + def g() = { + f0(1) + f1(1, 2) + f1(1, 2, 3) + f1(1, 2, 3, 4) + f1(1, j = 2, 3, 4) + f1(1, j = 2, k = 3, 4) + f6(1, 2, 3, 4, 5, 6, 7) + f6(1, 2, 3, 4, 5, 6, 7, 8) + f12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) + () + } +} diff --git a/test/files/neg/t876.check b/test/files/neg/t876.check index 04c5c8f22e97..91dcbfd288e2 100644 --- a/test/files/neg/t876.check +++ b/test/files/neg/t876.check @@ -1,4 +1,4 @@ -t876.scala:25: error: too many arguments for method apply: (key: AssertionError.A)manager.B in class HashMap +t876.scala:25: error: too many arguments (2) for method apply: (key: AssertionError.A)manager.B in class HashMap assert(manager.map(A2) == List(manager.map(A2, A1))) ^ one error found From 40b42ae71779fb333259674b05f28de45219939d Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 11 May 2016 14:32:50 -0700 Subject: [PATCH 016/153] SI-8667 Caret at bad arg Pick the first excessive positional arg for the caret. Note that erroring on named args doesn't do the obvious thing in this regard. If `k` was removed from the signature, then `f(k=1, i=2, j=3)` doesn't tell us much about the wrong arg, because naming takes the `k=1` as an assignment, `i` as duplicate naming. No arg is deemed extra, though further inspection of the conflicting args might get there. Since assignment syntax in parens is more|less deprecated (?), no more effort is done here. --- .../tools/nsc/typechecker/ContextErrors.scala | 18 ++++-- .../scala/tools/nsc/typechecker/Typers.scala | 7 +-- test/files/neg/eta-expand-star.check | 2 +- .../neg/macro-invalidusage-badargs.check | 2 +- test/files/neg/multi-array.check | 2 +- test/files/neg/protected-constructors.check | 7 ++- test/files/neg/t1112.check | 2 +- test/files/neg/t1523.check | 2 +- test/files/neg/t6920.check | 2 +- test/files/neg/t7157.check | 24 ++++---- test/files/neg/t8006.check | 2 +- test/files/neg/t8035-no-adapted-args.check | 2 +- test/files/neg/t8667.check | 56 +++++++++++-------- test/files/neg/t8667.scala | 4 +- test/files/neg/t876.check | 2 +- 15 files changed, 79 insertions(+), 55 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index e1055144f8c7..6b30d3834c1f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -538,7 +538,14 @@ trait ContextErrors { def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) = NormalTypeError(tree, "macro applications do not support named and/or default arguments") - def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree, expected: Int, supplied: Int, unknowns: List[Name]) = { + def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree, formals: List[Type], args: List[Tree], namelessArgs: List[Tree], argPos: Array[Int]) = { + val expected = formals.size + val supplied = args.size + // pick a caret. For f(k=1,i=2,j=3), argPos[0,-1,1] b/c `k=1` taken as arg0 + val excessive = { + val i = argPos.indexWhere(_ >= expected) + if (i < 0) tree else args(i min (supplied - 1)) + } val msg = { val badappl = { val excess = supplied - expected @@ -548,13 +555,16 @@ trait ContextErrors { else if (excess < 3 && expected <= 5) s"too many arguments ($supplied) for $target" else if (expected > 10) s"$supplied arguments but expected $expected for $target" else { - val oneOf = + val more = if (excess == 1) "one more argument" else if (excess > 0) s"$excess more arguments" else "too many arguments" - s"$oneOf than can be applied to $target" + s"$more than can be applied to $target" } } + val unknowns = (namelessArgs zip args) collect { + case (_: Assign, AssignOrNamedArg(Ident(name), _)) => name + } val suppl = unknowns.size match { case 0 => "" @@ -563,7 +573,7 @@ trait ContextErrors { } s"${badappl}${suppl}" } - NormalTypeError(tree, msg) + NormalTypeError(excessive, msg) } // can it still happen? see test case neg/overloaded-unapply.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1d24d8c232c0..286de993dbcc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3331,11 +3331,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper duplErrorTree(WrongNumberOfArgsError(tree, fun)) } else if (lencmp > 0) { tryTupleApply orElse duplErrorTree { - val (namelessArgs, _) = removeNames(Typer.this)(args, params) - val wrongs = (namelessArgs zip args) collect { - case (_: Assign, AssignOrNamedArg(Ident(name), _)) => name - } - TooManyArgsNamesDefaultsError(tree, fun, expected = formals.size, supplied = args.size, wrongs) + val (namelessArgs, argPos) = removeNames(Typer.this)(args, params) + TooManyArgsNamesDefaultsError(tree, fun, formals, args, namelessArgs, argPos) } } else if (lencmp == 0) { // we don't need defaults. names were used, so this application is transformed diff --git a/test/files/neg/eta-expand-star.check b/test/files/neg/eta-expand-star.check index f25e0a41ffad..eba17210148e 100644 --- a/test/files/neg/eta-expand-star.check +++ b/test/files/neg/eta-expand-star.check @@ -1,4 +1,4 @@ eta-expand-star.scala:6: error: too many arguments (2) for method apply: (v1: Seq[T])Unit in trait Function1 g(1, 2) - ^ + ^ one error found diff --git a/test/files/neg/macro-invalidusage-badargs.check b/test/files/neg/macro-invalidusage-badargs.check index 2f5f6d106423..ee549c45cbeb 100644 --- a/test/files/neg/macro-invalidusage-badargs.check +++ b/test/files/neg/macro-invalidusage-badargs.check @@ -15,5 +15,5 @@ Unspecified value parameter x. ^ Macros_Test_2.scala:9: error: too many arguments (2) for macro method foo: (x: Int)Int foo(4, 2) - ^ + ^ 5 errors found diff --git a/test/files/neg/multi-array.check b/test/files/neg/multi-array.check index a71f9b864af4..06ffdc9fbc33 100644 --- a/test/files/neg/multi-array.check +++ b/test/files/neg/multi-array.check @@ -1,4 +1,4 @@ multi-array.scala:7: error: too many arguments (2) for constructor Array: (_length: Int)Array[T] val a: Array[Int] = new Array(10, 10) - ^ + ^ one error found diff --git a/test/files/neg/protected-constructors.check b/test/files/neg/protected-constructors.check index 5c880cb67206..0279f5815d2e 100644 --- a/test/files/neg/protected-constructors.check +++ b/test/files/neg/protected-constructors.check @@ -1,6 +1,6 @@ protected-constructors.scala:17: error: no arguments allowed for nullary constructor Foo1: ()dingus.Foo1 val foo1 = new Foo1("abc") - ^ + ^ protected-constructors.scala:18: error: constructor Foo2 in class Foo2 cannot be accessed in object P Access to protected constructor Foo2 not permitted because enclosing object P in package hungus is not a subclass of @@ -19,4 +19,7 @@ protected-constructors.scala:15: error: class Foo3 in object Ding cannot be acce object Ding in package dingus where target is defined class Bar3 extends Ding.Foo3("abc") ^ -four errors found +protected-constructors.scala:15: error: no arguments allowed for nullary constructor Object: ()Object + class Bar3 extends Ding.Foo3("abc") + ^ +5 errors found diff --git a/test/files/neg/t1112.check b/test/files/neg/t1112.check index 9c1254d17655..e6058bf176f8 100644 --- a/test/files/neg/t1112.check +++ b/test/files/neg/t1112.check @@ -1,4 +1,4 @@ t1112.scala:12: error: too many arguments (2) for method call: (p: Int)(f: => Test.this.Type1)Unit call(0,() => System.out.println("here we are")) - ^ + ^ one error found diff --git a/test/files/neg/t1523.check b/test/files/neg/t1523.check index 656845a4578d..273d0f8cf77a 100644 --- a/test/files/neg/t1523.check +++ b/test/files/neg/t1523.check @@ -1,4 +1,4 @@ t1523.scala:4: error: 25 more arguments than can be applied to method bug: (x: Any)Any def go() = bug("a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a") - ^ + ^ one error found diff --git a/test/files/neg/t6920.check b/test/files/neg/t6920.check index 4e33aca3bc9a..d10abff03cc0 100644 --- a/test/files/neg/t6920.check +++ b/test/files/neg/t6920.check @@ -2,5 +2,5 @@ t6920.scala:9: error: too many arguments (2) for method applyDynamicNamed: (valu error after rewriting to CompilerError.this.test.applyDynamicNamed("crushTheCompiler")(scala.Tuple2("a", 1), scala.Tuple2("b", 2)) possible cause: maybe a wrong Dynamic method signature? test.crushTheCompiler(a = 1, b = 2) - ^ + ^ one error found diff --git a/test/files/neg/t7157.check b/test/files/neg/t7157.check index a043c5d40370..0b813949469b 100644 --- a/test/files/neg/t7157.check +++ b/test/files/neg/t7157.check @@ -1,22 +1,22 @@ Test_2.scala:5: error: no arguments allowed for nullary macro method m1_0_0: ()Unit m1_0_0(1) - ^ + ^ Test_2.scala:6: error: no arguments allowed for nullary macro method m1_0_0: ()Unit m1_0_0(1, 2) - ^ + ^ Test_2.scala:7: error: no arguments allowed for nullary macro method m1_0_0: ()Unit m1_0_0(1, 2, 3) - ^ + ^ Test_2.scala:9: error: not enough arguments for macro method m1_1_1: (x: Int)Unit. Unspecified value parameter x. m1_1_1() ^ Test_2.scala:11: error: too many arguments (2) for macro method m1_1_1: (x: Int)Unit m1_1_1(1, 2) - ^ + ^ Test_2.scala:12: error: too many arguments (3) for macro method m1_1_1: (x: Int)Unit m1_1_1(1, 2, 3) - ^ + ^ Test_2.scala:14: error: not enough arguments for macro method m1_2_2: (x: Int, y: Int)Unit. Unspecified value parameters x, y. m1_2_2() @@ -27,7 +27,7 @@ Unspecified value parameter y. ^ Test_2.scala:17: error: too many arguments (3) for macro method m1_2_2: (x: Int, y: Int)Unit m1_2_2(1, 2, 3) - ^ + ^ Test_2.scala:24: error: not enough arguments for macro method m1_1_inf: (x: Int, y: Int*)Unit. Unspecified value parameters x, y. m1_1_inf() @@ -42,23 +42,23 @@ Unspecified value parameters y, z. ^ Test_2.scala:35: error: no arguments allowed for nullary macro method m2_0_0: ()Unit m2_0_0()(1) - ^ + ^ Test_2.scala:36: error: no arguments allowed for nullary macro method m2_0_0: ()Unit m2_0_0()(1, 2) - ^ + ^ Test_2.scala:37: error: no arguments allowed for nullary macro method m2_0_0: ()Unit m2_0_0()(1, 2, 3) - ^ + ^ Test_2.scala:39: error: not enough arguments for macro method m2_1_1: (x: Int)Unit. Unspecified value parameter x. m2_1_1()() ^ Test_2.scala:41: error: too many arguments (2) for macro method m2_1_1: (x: Int)Unit m2_1_1()(1, 2) - ^ + ^ Test_2.scala:42: error: too many arguments (3) for macro method m2_1_1: (x: Int)Unit m2_1_1()(1, 2, 3) - ^ + ^ Test_2.scala:44: error: not enough arguments for macro method m2_2_2: (x: Int, y: Int)Unit. Unspecified value parameters x, y. m2_2_2()() @@ -69,7 +69,7 @@ Unspecified value parameter y. ^ Test_2.scala:47: error: too many arguments (3) for macro method m2_2_2: (x: Int, y: Int)Unit m2_2_2()(1, 2, 3) - ^ + ^ Test_2.scala:54: error: not enough arguments for macro method m2_1_inf: (x: Int, y: Int*)Unit. Unspecified value parameters x, y. m2_1_inf()() diff --git a/test/files/neg/t8006.check b/test/files/neg/t8006.check index 4e130670e4d4..6152d0fba364 100644 --- a/test/files/neg/t8006.check +++ b/test/files/neg/t8006.check @@ -2,5 +2,5 @@ t8006.scala:3: error: too many arguments (2) for method applyDynamicNamed: (valu error after rewriting to X.this.d.applyDynamicNamed("meth")(scala.Tuple2("value1", 10), scala.Tuple2("value2", 100)) possible cause: maybe a wrong Dynamic method signature? d.meth(value1 = 10, value2 = 100) // two arguments here, but only one is allowed - ^ + ^ one error found diff --git a/test/files/neg/t8035-no-adapted-args.check b/test/files/neg/t8035-no-adapted-args.check index 4b3cb39c769f..0115dddc91a3 100644 --- a/test/files/neg/t8035-no-adapted-args.check +++ b/test/files/neg/t8035-no-adapted-args.check @@ -6,7 +6,7 @@ t8035-no-adapted-args.scala:4: warning: No automatic adaptation here: use explic ^ t8035-no-adapted-args.scala:4: error: too many arguments (3) for method f: (x: (Int, Int, Int))Int f(1, 2, 3) - ^ + ^ t8035-no-adapted-args.scala:5: warning: No automatic adaptation here: use explicit parentheses. signature: Test.f[T](x: T): Int given arguments: diff --git a/test/files/neg/t8667.check b/test/files/neg/t8667.check index 4c3bcb78c829..82451ee5d6ad 100644 --- a/test/files/neg/t8667.check +++ b/test/files/neg/t8667.check @@ -1,7 +1,7 @@ t8667.scala:6: error: too many arguments (3) for constructor C: (a: Int, b: Int)C Note that 'c' is not a parameter name of the invoked method. def c2 = new C(a = 42, b = 17, c = 5) - ^ + ^ t8667.scala:7: error: unknown parameter name: c def c3 = new C(b = 42, a = 17, c = 5) ^ @@ -25,9 +25,13 @@ t8667.scala:10: error: too many arguments (3) for constructor C: (a: Int, b: Int Note that 'c' is not a parameter name of the invoked method. def c6 = new C(a = 42, c = 17, b = 5) ^ +t8667.scala:11: error: parameter 'a' is already specified at parameter position 1 +Note that 'c' is not a parameter name of the invoked method. + def c7 = new C(c = 42, a = 17, b = 5) + ^ t8667.scala:11: error: too many arguments (3) for constructor C: (a: Int, b: Int)C Note that 'c' is not a parameter name of the invoked method. - def c7 = new C(42, 17, c = 5) + def c7 = new C(c = 42, a = 17, b = 5) ^ t8667.scala:12: error: parameter 'b' is already specified at parameter position 2 def c8 = new C(42, 17, b = 5) @@ -42,38 +46,46 @@ Note that 'c' is not a parameter name of the invoked method. t8667.scala:13: error: too many arguments (4) for constructor C: (a: Int, b: Int)C Note that 'c', 'd' are not parameter names of the invoked method. def c9 = new C(a = 42, c = 17, d = 3, b = 5) - ^ + ^ t8667.scala:14: error: too many arguments (4) for constructor C: (a: Int, b: Int)C Note that 'd', 'c' are not parameter names of the invoked method. def c0 = new C(42, 17, d = 3, c = 5) - ^ -t8667.scala:24: error: no arguments allowed for nullary method f0: ()Int + ^ +t8667.scala:25: error: no arguments allowed for nullary method f0: ()Int f0(1) - ^ -t8667.scala:25: error: too many arguments (2) for method f1: (i: Int)Int + ^ +t8667.scala:26: error: too many arguments (2) for method f1: (i: Int)Int f1(1, 2) - ^ -t8667.scala:26: error: too many arguments (3) for method f1: (i: Int)Int + ^ +t8667.scala:27: error: too many arguments (3) for method f1: (i: Int)Int f1(1, 2, 3) - ^ -t8667.scala:27: error: 3 more arguments than can be applied to method f1: (i: Int)Int - f1(1, 2, 3, 4) - ^ + ^ t8667.scala:28: error: 3 more arguments than can be applied to method f1: (i: Int)Int + f1(1, 2, 3, 4) + ^ +t8667.scala:29: error: 3 more arguments than can be applied to method f1: (i: Int)Int Note that 'j' is not a parameter name of the invoked method. f1(1, j = 2, 3, 4) - ^ -t8667.scala:29: error: 3 more arguments than can be applied to method f1: (i: Int)Int + ^ +t8667.scala:30: error: 3 more arguments than can be applied to method f1: (i: Int)Int Note that 'j', 'k' are not parameter names of the invoked method. f1(1, j = 2, k = 3, 4) + ^ +t8667.scala:31: error: parameter 'i' is already specified at parameter position 1 +Note that 'k' is not a parameter name of the invoked method. + f2(k = 1, i = 2, j = 3) + ^ +t8667.scala:31: error: too many arguments (3) for method f2: (i: Int, j: Int)Int +Note that 'k' is not a parameter name of the invoked method. + f2(k = 1, i = 2, j = 3) ^ -t8667.scala:30: error: one more argument than can be applied to method f6: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int)Int +t8667.scala:32: error: one more argument than can be applied to method f6: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int)Int f6(1, 2, 3, 4, 5, 6, 7) - ^ -t8667.scala:31: error: 2 more arguments than can be applied to method f6: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int)Int + ^ +t8667.scala:33: error: 2 more arguments than can be applied to method f6: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int)Int f6(1, 2, 3, 4, 5, 6, 7, 8) - ^ -t8667.scala:32: error: 15 arguments but expected 12 for method f12: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int, s: Int, t: Int)Int + ^ +t8667.scala:34: error: 15 arguments but expected 12 for method f12: (i: Int, j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int, s: Int, t: Int)Int f12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) - ^ -23 errors found + ^ +26 errors found diff --git a/test/files/neg/t8667.scala b/test/files/neg/t8667.scala index fe17eac84f6c..d55582ca6b8f 100644 --- a/test/files/neg/t8667.scala +++ b/test/files/neg/t8667.scala @@ -8,7 +8,7 @@ trait T { def c4 = new C(b = 42, a = 17, 5) def c5 = new C(a = 42, c = 17) def c6 = new C(a = 42, c = 17, b = 5) - def c7 = new C(42, 17, c = 5) + def c7 = new C(c = 42, a = 17, b = 5) def c8 = new C(42, 17, b = 5) def c9 = new C(a = 42, c = 17, d = 3, b = 5) def c0 = new C(42, 17, d = 3, c = 5) @@ -17,6 +17,7 @@ trait T { trait X { def f0() = 42 def f1(i: Int) = 42 + def f2(i: Int, j: Int) = 42 def f6(i: Int, j: Int, k: Int, l: Int, m: Int, n: Int) = 42 def f12(i: Int, j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int, s: Int, t: Int) = 42 @@ -27,6 +28,7 @@ trait X { f1(1, 2, 3, 4) f1(1, j = 2, 3, 4) f1(1, j = 2, k = 3, 4) + f2(k = 1, i = 2, j = 3) f6(1, 2, 3, 4, 5, 6, 7) f6(1, 2, 3, 4, 5, 6, 7, 8) f12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) diff --git a/test/files/neg/t876.check b/test/files/neg/t876.check index 91dcbfd288e2..7df2e126a6f0 100644 --- a/test/files/neg/t876.check +++ b/test/files/neg/t876.check @@ -1,4 +1,4 @@ t876.scala:25: error: too many arguments (2) for method apply: (key: AssertionError.A)manager.B in class HashMap assert(manager.map(A2) == List(manager.map(A2, A1))) - ^ + ^ one error found From 45e607d3879623d5163f47c17c717904f6867ef6 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Sat, 14 May 2016 14:12:43 +0100 Subject: [PATCH 017/153] SI-9361 fixed assert allowing display of improved error message. --- .../scala/tools/nsc/typechecker/ContextErrors.scala | 5 +++-- test/files/neg/t9361.check | 11 +++++++++++ test/files/neg/t9361.scala | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 test/files/neg/t9361.check create mode 100644 test/files/neg/t9361.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index e190b57017b7..90ccaefe432a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -198,7 +198,7 @@ trait ContextErrors { val foundType: Type = req.dealiasWiden match { case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass => val retyped = typed (tree.duplicate.clearType()) - val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic) + val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic && !sym.isErroneous) if (foundDecls.isEmpty || (found.typeSymbol eq NoSymbol)) found else { // The members arrive marked private, presumably because there was no @@ -212,7 +212,8 @@ trait ContextErrors { case _ => found } - assert(!foundType.isErroneous && !req.isErroneous, (foundType, req)) + assert(!foundType.isErroneous, s"AdaptTypeError - foundType is Erroneous: $foundType") + assert(!req.isErroneous, s"AdaptTypeError - req is Erroneous: $req") issueNormalTypeError(callee, withAddendum(callee.pos)(typeErrorMsg(foundType, req))) infer.explainTypes(foundType, req) diff --git a/test/files/neg/t9361.check b/test/files/neg/t9361.check new file mode 100644 index 000000000000..847d137f7d6c --- /dev/null +++ b/test/files/neg/t9361.check @@ -0,0 +1,11 @@ +t9361.scala:4: error: type mismatch; + found : Tc[_$2] where type _$2 + required: Nothing[] + new Foo { def tc = null.asInstanceOf[Tc[_]] } + ^ +t9361.scala:4: error: type mismatch; + found : Foo[Nothing] + required: Foo[Tc]{type T = Nothing} + new Foo { def tc = null.asInstanceOf[Tc[_]] } + ^ +two errors found diff --git a/test/files/neg/t9361.scala b/test/files/neg/t9361.scala new file mode 100644 index 000000000000..b689461e4d56 --- /dev/null +++ b/test/files/neg/t9361.scala @@ -0,0 +1,5 @@ +abstract class Foo[Tc[_]] { def tc: Tc[_] } +object Foo { + def foo[Tc[_]](): Foo[Tc] { type T = Nothing } = + new Foo { def tc = null.asInstanceOf[Tc[_]] } +} From 139f9a0f97a24c8f8b2db5947b6cb3d68d5682fb Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Tue, 17 May 2016 12:38:28 +0900 Subject: [PATCH 018/153] Make Range.Partial a value class --- src/library/scala/collection/immutable/Range.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index d3fe367e5035..2fe75343d153 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -512,7 +512,7 @@ object Range { // As there is no appealing default step size for not-really-integral ranges, // we offer a partially constructed object. - class Partial[T, U](f: T => U) { + class Partial[T, U](private val f: T => U) extends AnyVal { def by(x: T): U = f(x) } From 73ca44be579e5100706d174f18025fc4487e9cb9 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 16 May 2016 16:24:50 -0700 Subject: [PATCH 019/153] SI-4625 Recognize App in script Cheap name test: if the script object extends "App", take it for a main-bearing parent. Note that if `-Xscript` is not `Main`, the default, then the source is taken as a snippet and there is no attempt to locate an existing `main` method. --- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 6 +++++- test/files/run/t4625.check | 1 + test/files/run/t4625.scala | 7 +++++++ test/files/run/t4625.script | 5 +++++ 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/files/run/t4625.check create mode 100644 test/files/run/t4625.scala create mode 100644 test/files/run/t4625.script diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index c04d305f9e43..7af5c505de1d 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -380,11 +380,15 @@ self => case DefDef(_, nme.main, Nil, List(_), _, _) => true case _ => false } + def isApp(t: Tree) = t match { + case Template(ps, _, _) => ps.exists { case Ident(x) if x.decoded == "App" => true ; case _ => false } + case _ => false + } /* For now we require there only be one top level object. */ var seenModule = false val newStmts = stmts collect { case t @ Import(_, _) => t - case md @ ModuleDef(mods, name, template) if !seenModule && (md exists isMainMethod) => + case md @ ModuleDef(mods, name, template) if !seenModule && (isApp(template) || md.exists(isMainMethod)) => seenModule = true /* This slightly hacky situation arises because we have no way to communicate * back to the scriptrunner what the name of the program is. Even if we were diff --git a/test/files/run/t4625.check b/test/files/run/t4625.check new file mode 100644 index 000000000000..e4a4d15b8754 --- /dev/null +++ b/test/files/run/t4625.check @@ -0,0 +1 @@ +Test ran. diff --git a/test/files/run/t4625.scala b/test/files/run/t4625.scala new file mode 100644 index 000000000000..44f62252201c --- /dev/null +++ b/test/files/run/t4625.scala @@ -0,0 +1,7 @@ + +import scala.tools.partest.ScriptTest + +object Test extends ScriptTest { + // must be called Main to get probing treatment in parser + override def testmain = "Main" +} diff --git a/test/files/run/t4625.script b/test/files/run/t4625.script new file mode 100644 index 000000000000..600ceacbb653 --- /dev/null +++ b/test/files/run/t4625.script @@ -0,0 +1,5 @@ + +object Main extends Runnable with App { + def run() = println("Test ran.") + run() +} From 5bcefbe1889a1b8e1f9bac04090428eaaa7b2fd3 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 16 May 2016 22:57:51 -0700 Subject: [PATCH 020/153] SI-4625 App is a thing Scripting knows it by name. --- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 5 ++++- src/reflect/scala/reflect/internal/StdNames.scala | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 7af5c505de1d..358ccb5dc3a8 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -365,12 +365,15 @@ self => val stmts = parseStats() def mainModuleName = newTermName(settings.script.value) + /* If there is only a single object template in the file and it has a * suitable main method, we will use it rather than building another object * around it. Since objects are loaded lazily the whole script would have * been a no-op, so we're not taking much liberty. */ def searchForMain(): Option[Tree] = { + import PartialFunction.cond + /* Have to be fairly liberal about what constitutes a main method since * nothing has been typed yet - for instance we can't assume the parameter * type will look exactly like "Array[String]" as it could have been renamed @@ -381,7 +384,7 @@ self => case _ => false } def isApp(t: Tree) = t match { - case Template(ps, _, _) => ps.exists { case Ident(x) if x.decoded == "App" => true ; case _ => false } + case Template(ps, _, _) => ps.exists(cond(_) { case Ident(tpnme.App) => true }) case _ => false } /* For now we require there only be one top level object. */ diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 52558d939501..a0688e129cff 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -240,6 +240,7 @@ trait StdNames { final val Any: NameType = "Any" final val AnyVal: NameType = "AnyVal" + final val App: NameType = "App" final val FlagSet: NameType = "FlagSet" final val Mirror: NameType = "Mirror" final val Modifiers: NameType = "Modifiers" From ee365cccaf740d5ec353718556b010137f4cdd4d Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 16 May 2016 23:28:16 -0700 Subject: [PATCH 021/153] SI-4625 Permit arbitrary top-level in script In an unwrapped script, where a `main` entry point is discovered in a top-level object, retain all top-level classes. Everything winds up in the default package. --- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 4 +++- test/files/run/t4625b.check | 1 + test/files/run/t4625b.scala | 7 +++++++ test/files/run/t4625b.script | 8 ++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 test/files/run/t4625b.check create mode 100644 test/files/run/t4625b.scala create mode 100644 test/files/run/t4625b.script diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 358ccb5dc3a8..1ece580b96d6 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -384,7 +384,7 @@ self => case _ => false } def isApp(t: Tree) = t match { - case Template(ps, _, _) => ps.exists(cond(_) { case Ident(tpnme.App) => true }) + case Template(parents, _, _) => parents.exists(cond(_) { case Ident(tpnme.App) => true }) case _ => false } /* For now we require there only be one top level object. */ @@ -402,6 +402,8 @@ self => */ if (name == mainModuleName) md else treeCopy.ModuleDef(md, mods, mainModuleName, template) + case md @ ModuleDef(_, _, _) => md + case cd @ ClassDef(_, _, _, _) => cd case _ => /* If we see anything but the above, fail. */ return None diff --git a/test/files/run/t4625b.check b/test/files/run/t4625b.check new file mode 100644 index 000000000000..e79539a5c4ee --- /dev/null +++ b/test/files/run/t4625b.check @@ -0,0 +1 @@ +Misc top-level detritus diff --git a/test/files/run/t4625b.scala b/test/files/run/t4625b.scala new file mode 100644 index 000000000000..44f62252201c --- /dev/null +++ b/test/files/run/t4625b.scala @@ -0,0 +1,7 @@ + +import scala.tools.partest.ScriptTest + +object Test extends ScriptTest { + // must be called Main to get probing treatment in parser + override def testmain = "Main" +} diff --git a/test/files/run/t4625b.script b/test/files/run/t4625b.script new file mode 100644 index 000000000000..f21a553dd12d --- /dev/null +++ b/test/files/run/t4625b.script @@ -0,0 +1,8 @@ + +trait X { def x = "Misc top-level detritus" } + +object Bumpkus + +object Main extends X with App { + println(x) +} From e753135f02a8177e809937e56fed5c054091691f Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 17 May 2016 00:00:52 -0700 Subject: [PATCH 022/153] SI-4625 Warn when discarding script object It's pretty confusing when your script object becomes a local and then nothing happens. Such as when you're writing a test and it takes forever to figure out what's going on. --- .../scala/tools/nsc/ast/parser/Parsers.scala | 15 +++++++++++---- test/files/run/t4625c.check | 3 +++ test/files/run/t4625c.scala | 7 +++++++ test/files/run/t4625c.script | 6 ++++++ 4 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 test/files/run/t4625c.check create mode 100644 test/files/run/t4625c.scala create mode 100644 test/files/run/t4625c.script diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 1ece580b96d6..c2f2141fd3ec 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -389,8 +389,8 @@ self => } /* For now we require there only be one top level object. */ var seenModule = false + var disallowed = EmptyTree: Tree val newStmts = stmts collect { - case t @ Import(_, _) => t case md @ ModuleDef(mods, name, template) if !seenModule && (isApp(template) || md.exists(isMainMethod)) => seenModule = true /* This slightly hacky situation arises because we have no way to communicate @@ -404,11 +404,18 @@ self => else treeCopy.ModuleDef(md, mods, mainModuleName, template) case md @ ModuleDef(_, _, _) => md case cd @ ClassDef(_, _, _, _) => cd - case _ => + case t @ Import(_, _) => t + case t => /* If we see anything but the above, fail. */ - return None + disallowed = t + EmptyTree + } + if (disallowed.isEmpty) Some(makeEmptyPackage(0, newStmts)) + else { + if (seenModule) + warning(disallowed.pos.point, "Script has a main object but statement is disallowed") + None } - Some(makeEmptyPackage(0, newStmts)) } if (mainModuleName == newTermName(ScriptRunner.defaultScriptMain)) diff --git a/test/files/run/t4625c.check b/test/files/run/t4625c.check new file mode 100644 index 000000000000..6acb1710b907 --- /dev/null +++ b/test/files/run/t4625c.check @@ -0,0 +1,3 @@ +newSource1.scala:2: warning: Script has a main object but statement is disallowed +val x = "value x" + ^ diff --git a/test/files/run/t4625c.scala b/test/files/run/t4625c.scala new file mode 100644 index 000000000000..44f62252201c --- /dev/null +++ b/test/files/run/t4625c.scala @@ -0,0 +1,7 @@ + +import scala.tools.partest.ScriptTest + +object Test extends ScriptTest { + // must be called Main to get probing treatment in parser + override def testmain = "Main" +} diff --git a/test/files/run/t4625c.script b/test/files/run/t4625c.script new file mode 100644 index 000000000000..fa14f43950df --- /dev/null +++ b/test/files/run/t4625c.script @@ -0,0 +1,6 @@ + +val x = "value x" + +object Main extends App { + println(s"Test ran with $x.") +} From c2f67d2e14f90b0bda1bc2ae7245d104e7d0087b Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 17 May 2016 08:33:46 +0200 Subject: [PATCH 023/153] Move t8449 to correct place Follow-up for https://github.com/scala/scala/pull/4117 --- test/files/{ => pos}/t8449/Client.scala | 0 test/files/{ => pos}/t8449/Test.java | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/files/{ => pos}/t8449/Client.scala (100%) rename test/files/{ => pos}/t8449/Test.java (100%) diff --git a/test/files/t8449/Client.scala b/test/files/pos/t8449/Client.scala similarity index 100% rename from test/files/t8449/Client.scala rename to test/files/pos/t8449/Client.scala diff --git a/test/files/t8449/Test.java b/test/files/pos/t8449/Test.java similarity index 100% rename from test/files/t8449/Test.java rename to test/files/pos/t8449/Test.java From 443fa04653f8f2d80df721885192ee4adefce3c5 Mon Sep 17 00:00:00 2001 From: Krzysztof Romanowski Date: Tue, 17 May 2016 12:22:30 +0200 Subject: [PATCH 024/153] Remove default value for sourcepath in scalac (ant version). (#5166) --- src/compiler/scala/tools/ant/Scalac.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala index f46f014096b0..a6024d438870 100644 --- a/src/compiler/scala/tools/ant/Scalac.scala +++ b/src/compiler/scala/tools/ant/Scalac.scala @@ -577,8 +577,6 @@ class Scalac extends ScalaMatchingTask with ScalacShared { settings.classpath.value = asString(getClasspath) if (!sourcepath.isEmpty) settings.sourcepath.value = asString(getSourcepath) - else if (origin.get.size() > 0) - settings.sourcepath.value = origin.get.list()(0) if (!bootclasspath.isEmpty) settings.bootclasspath.value = asString(getBootclasspath) if (!extdirs.isEmpty) settings.extdirs.value = asString(getExtdirs) From 883fdd74d63a54495f4013eef81c9b5ebc850d1c Mon Sep 17 00:00:00 2001 From: peterz Date: Tue, 10 May 2016 11:54:21 +0300 Subject: [PATCH 025/153] SI-5463 Check .jars before using them Make broken JAR files on compiler classpath cause a fatal error --- .../nsc/classpath/AggregateClassPath.scala | 12 ++++++++++- test/files/run/t5463.scala | 21 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 test/files/run/t5463.scala diff --git a/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala b/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala index 6b435542a309..a1af3413ead6 100644 --- a/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/AggregateClassPath.scala @@ -6,6 +6,7 @@ package scala.tools.nsc.classpath import java.net.URL import scala.annotation.tailrec import scala.collection.mutable.ArrayBuffer +import scala.reflect.internal.FatalError import scala.reflect.io.AbstractFile import scala.tools.nsc.util.ClassPath import scala.tools.nsc.util.ClassRepresentation @@ -72,7 +73,16 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath { getDistinctEntries(_.sources(inPackage)) override private[nsc] def list(inPackage: String): ClassPathEntries = { - val (packages, classesAndSources) = aggregates.map(_.list(inPackage)).unzip + val (packages, classesAndSources) = aggregates.map { cp => + try { + cp.list(inPackage) + } catch { + case ex: java.io.IOException => + val e = new FatalError(ex.getMessage) + e.initCause(ex) + throw e + } + }.unzip val distinctPackages = packages.flatten.distinct val distinctClassesAndSources = mergeClassesAndSources(classesAndSources: _*) ClassPathEntries(distinctPackages, distinctClassesAndSources) diff --git a/test/files/run/t5463.scala b/test/files/run/t5463.scala new file mode 100644 index 000000000000..30b8306156d3 --- /dev/null +++ b/test/files/run/t5463.scala @@ -0,0 +1,21 @@ +import scala.reflect.internal.FatalError +import scala.tools.partest.DirectTest + +object Test extends DirectTest { + + def code = "class A" + + override def show(): Unit = { + // Create a broken JAR file and put it on compiler classpath + val jarpath = testOutput.path + "/notajar.jar" + scala.reflect.io.File(jarpath).writeAll("This isn't really a JAR file") + + val classpath = List(sys.props("partest.lib"), jarpath, testOutput.path) mkString sys.props("path.separator") + try { + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + throw new Error("Compilation should have failed"); + } catch { + case ex: FatalError => // this is expected + } + } +} From 7f514bba9ff1993ccbfdcf4a37a8045849f1647a Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 17 May 2016 14:12:57 -0700 Subject: [PATCH 026/153] SI-4625 Warn on first non-toplevel only Fixed the warning when main module is accompanied by snippets. Minor clean-up so even I can follow what is returned. --- .../scala/tools/nsc/ast/parser/Parsers.scala | 88 ++++++++++--------- test/files/run/t4625c.script | 1 + 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index c2f2141fd3ec..308669256dc7 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -371,7 +371,7 @@ self => * around it. Since objects are loaded lazily the whole script would have * been a no-op, so we're not taking much liberty. */ - def searchForMain(): Option[Tree] = { + def searchForMain(): Tree = { import PartialFunction.cond /* Have to be fairly liberal about what constitutes a main method since @@ -387,10 +387,10 @@ self => case Template(parents, _, _) => parents.exists(cond(_) { case Ident(tpnme.App) => true }) case _ => false } - /* For now we require there only be one top level object. */ + /* We allow only one main module. */ var seenModule = false var disallowed = EmptyTree: Tree - val newStmts = stmts collect { + val newStmts = stmts.map { case md @ ModuleDef(mods, name, template) if !seenModule && (isApp(template) || md.exists(isMainMethod)) => seenModule = true /* This slightly hacky situation arises because we have no way to communicate @@ -407,54 +407,58 @@ self => case t @ Import(_, _) => t case t => /* If we see anything but the above, fail. */ - disallowed = t + if (disallowed.isEmpty) disallowed = t EmptyTree } - if (disallowed.isEmpty) Some(makeEmptyPackage(0, newStmts)) + if (disallowed.isEmpty) makeEmptyPackage(0, newStmts) else { if (seenModule) warning(disallowed.pos.point, "Script has a main object but statement is disallowed") - None + EmptyTree } } - if (mainModuleName == newTermName(ScriptRunner.defaultScriptMain)) - searchForMain() foreach { return _ } + def mainModule: Tree = + if (mainModuleName == newTermName(ScriptRunner.defaultScriptMain)) searchForMain() else EmptyTree - /* Here we are building an AST representing the following source fiction, - * where `moduleName` is from -Xscript (defaults to "Main") and are - * the result of parsing the script file. - * - * {{{ - * object moduleName { - * def main(args: Array[String]): Unit = - * new AnyRef { - * stmts - * } - * } - * }}} - */ - def emptyInit = DefDef( - NoMods, - nme.CONSTRUCTOR, - Nil, - ListOfNil, - TypeTree(), - Block(List(Apply(gen.mkSuperInitCall, Nil)), literalUnit) - ) - - // def main - def mainParamType = AppliedTypeTree(Ident(tpnme.Array), List(Ident(tpnme.String))) - def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.args, mainParamType, EmptyTree)) - def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), gen.mkAnonymousNew(stmts)) - - // object Main - def moduleName = newTermName(ScriptRunner scriptMain settings) - def moduleBody = Template(atInPos(scalaAnyRefConstr) :: Nil, noSelfType, List(emptyInit, mainDef)) - def moduleDef = ModuleDef(NoMods, moduleName, moduleBody) - - // package { ... } - makeEmptyPackage(0, moduleDef :: Nil) + def repackaged: Tree = { + /* Here we are building an AST representing the following source fiction, + * where `moduleName` is from -Xscript (defaults to "Main") and are + * the result of parsing the script file. + * + * {{{ + * object moduleName { + * def main(args: Array[String]): Unit = + * new AnyRef { + * stmts + * } + * } + * }}} + */ + def emptyInit = DefDef( + NoMods, + nme.CONSTRUCTOR, + Nil, + ListOfNil, + TypeTree(), + Block(List(Apply(gen.mkSuperInitCall, Nil)), literalUnit) + ) + + // def main + def mainParamType = AppliedTypeTree(Ident(tpnme.Array), List(Ident(tpnme.String))) + def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.args, mainParamType, EmptyTree)) + def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), gen.mkAnonymousNew(stmts)) + + // object Main + def moduleName = newTermName(ScriptRunner scriptMain settings) + def moduleBody = Template(atInPos(scalaAnyRefConstr) :: Nil, noSelfType, List(emptyInit, mainDef)) + def moduleDef = ModuleDef(NoMods, moduleName, moduleBody) + + // package { ... } + makeEmptyPackage(0, moduleDef :: Nil) + } + + mainModule orElse repackaged } /* --------------- PLACEHOLDERS ------------------------------------------- */ diff --git a/test/files/run/t4625c.script b/test/files/run/t4625c.script index fa14f43950df..16159208e05c 100644 --- a/test/files/run/t4625c.script +++ b/test/files/run/t4625c.script @@ -1,5 +1,6 @@ val x = "value x" +val y = "value y" object Main extends App { println(s"Test ran with $x.") From e483e49d7e53e15436890000b639cc06d31712e8 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 19 May 2016 12:13:38 +0200 Subject: [PATCH 027/153] [backport] identical readme in 2.11.x as in 2.12.x --- CONTRIBUTING.md | 28 ++- README.md | 380 +++++++++++++++++++++++------------------ src/intellij/README.md | 73 ++++++-- 3 files changed, 296 insertions(+), 185 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 617734210f06..47d27886231e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ In 2014, you -- the Scala community -- matched the core team at EPFL in number o We are super happy about this, and are eager to make your experience contributing to Scala productive and satisfying, so that we can keep up this growth. We can't do this alone (nor do we want to)! -This is why we're collecting these notes on how to contribute, and we hope you'll share your experience to improve the process for the next contributor! (Feel free to send a PR for this note, send your thoughts to scala-internals, or tweet about it to @adriaanm.) +This is why we're collecting these notes on how to contribute, and we hope you'll share your experience to improve the process for the next contributor! (Feel free to send a PR for this note, send your thoughts to gitter, scala-internals, or tweet about it to @adriaanm.) By the way, the team at Lightbend is: @adriaanm, @lrytz, @retronym, @SethTisue, and @szeiger. @@ -117,14 +117,32 @@ See the [scala-jenkins-infra repo](https://github.com/scala/scala-jenkins-infra) ### Pass code review -Your PR will need to be assigned to one or more reviewers. You can suggest reviewers yourself; if you're not sure, see the list in [README.md](README.md) or ask on scala-internals. +Your PR will need to be assigned to one or more reviewers. You can suggest reviewers +yourself; if you're not sure, see the list in [README.md](README.md) or ask on gitter +or scala-internals. -To assign a reviewer, add a "review by @reviewer" to your PR description. +To assign a reviewer, add a "review by @reviewer" to the PR description or in a +comment on your PR. NOTE: it's best not to @mention in commit messages, as github pings you every time a commit with your @name on it shuffles through the system (even in other repos, on merges,...). A reviewer gives the green light by commenting "LGTM" (looks good to me). -A review feedback may be addressed by pushing new commits to the request, if these commits stand on their own. +When including review feedback, we typically amend the changes into the existing commit(s) +and `push -f` to the branch. This is to keep the git history clean. Additional commits +are OK if they stand on their own. -Once all these conditions are met, and we agree with the change (we are available on scala-internals to discuss this beforehand, before you put in the coding work!), we will merge your changes. +Once all these conditions are met, and we agree with the change (we are available on +gitter or scala-internals to discuss this beforehand, before you put in the coding work!), +we will merge your changes. + +We use the following labels: + +Label | Description +-------------------------|:----------- +`reviewed` | automatically added by scabot when a comment prefixed with LGTM is posted +`welcome` | added by reviewer / queue curator to welcome someone's first PR (for highlighting in the release notes) +`release-notes` | added by reviewer / queue curator to make sure this PR is highlighted in the release notes +`on-hold` | added when this PR should not yet be merged, even though CI is green +`WIP` | added by the author if a PR is submitted for CI testing, needs more work to be complete +`assistance-appreciated` | added by the author if help by the community is appreciated to move a change forward diff --git a/README.md b/README.md index 9ef47494184e..6ebb4531765c 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ This is the official repository for the [Scala Programming Language](http://www. To contribute to the Scala Standard Library, Scala Compiler and Scala Language Specification, please send us a [pull request](https://help.github.com/articles/using-pull-requests/#fork--pull) from your fork of this repository! We do have to ask you to sign the [Scala CLA](http://www.lightbend.com/contribute/cla/scala) before we can merge any of your work into our code base, to protect its open source nature. -For more information on building and developing the core of Scala, read on! +For more information on building and developing the core of Scala, make sure to read +the rest of this README! -Please also check out: - -* our [guidelines for contributing](CONTRIBUTING.md). -* the ["Scala Hacker Guide"](http://scala-lang.org/contribute/hacker-guide.html) covers some of the same ground as this README, but in greater detail and in a more tutorial style, using a running example. +In order to get in touch with Scala contributors, join the +[scala/contributors](https://gitter.im/scala/contributors) gitter channel or post on the +[scala-internals mailing list](http://www.scala-lang.org/community/). # Reporting issues @@ -18,195 +18,247 @@ We're still using Jira for issue reporting, so please [report any issues](https: (We would love to start using GitHub Issues, but we're too resource-constrained to take on this migration right now.) # Get in touch! -If you need some help with your PR at any time, please feel free to @-mention anyone from the list below (or simply `@scala/team-core-scala`), and we will do our best to help you out: +If you need some help with your PR at any time, please feel free to @-mention anyone from the list below, and we will do our best to help you out: | username | talk to me about... | --------------------------------------------------------------------------------------------------|----------------------------------------------------------------|---------------------------------------------------| - | [`@adriaanm`](https://github.com/adriaanm) | type checker, pattern matcher, infrastructure, language spec | - | [`@SethTisue`](https://github.com/SethTisue) | build, developer docs, community build, Jenkins, library, the welcome-to-Scala experience | - | [`@retronym`](https://github.com/retronym) | compiler performance, weird compiler bugs, Java 8 lambdas, REPL | - | [`@Ichoran`](https://github.com/Ichoran) | collections library, performance | - | [`@lrytz`](https://github.com/lrytz) | optimizer, named & default arguments | - | [`@VladUreche`](https://github.com/VladUreche) | specialization, Scaladoc tool | - | [`@densh`](https://github.com/densh) | quasiquotes, parser, string interpolators, macros in standard library | - | [`@xeno-by`](https://github.com/xeno-by) | macros and reflection | - | [`@heathermiller`](https://github.com/heathermiller) | documentation | - | [`@dickwall`](https://github.com/dickwall) | process & community, documentation | - | [`@dragos`](https://github.com/dragos) | specialization, back end | - | [`@axel22`](https://github.com/axel22) | collections, concurrency, specialization | - | [`@janekdb`](https://github.com/janekdb) | documentation | + | [`@adriaanm`](https://github.com/adriaanm) | type checker, pattern matcher, infrastructure, language spec | + | [`@SethTisue`](https://github.com/SethTisue) | build, developer docs, community build, Jenkins, library, the welcome-to-Scala experience | + | [`@retronym`](https://github.com/retronym) | compiler performance, weird compiler bugs, Java 8 lambdas, REPL | + | [`@Ichoran`](https://github.com/Ichoran) | collections library, performance | + | [`@lrytz`](https://github.com/lrytz) | optimizer, named & default arguments | + | [`@VladUreche`](https://github.com/VladUreche) | specialization, Scaladoc tool | + | [`@densh`](https://github.com/densh) | quasiquotes, parser, string interpolators, macros in standard library | + | [`@xeno-by`](https://github.com/xeno-by) | macros and reflection | + | [`@heathermiller`](https://github.com/heathermiller) | documentation | + | [`@dickwall`](https://github.com/dickwall) | process & community, documentation | + | [`@dragos`](https://github.com/dragos) | specialization, back end | + | [`@axel22`](https://github.com/axel22) | collections, concurrency, specialization | + | [`@janekdb`](https://github.com/janekdb) | documentation | P.S.: If you have some spare time to help out around here, we would be delighted to add your name to this list! -# Handy Links - - [A wealth of documentation](http://docs.scala-lang.org) - - [mailing lists](http://www.scala-lang.org/community/) - - [Gitter room for Scala contributors](https://gitter.im/scala/contributors) - - [Scala CI](https://scala-ci.typesafe.com/) - - download the latest nightlies: - - [2.11.x](http://www.scala-lang.org/files/archive/nightly/2.11.x/) - - [2.12.x](http://www.scala-lang.org/files/archive/nightly/2.12.x/) - # Repository structure ``` scala/ -+--build.xml The main Ant build script, see also under src/build. -+--pull-binary-libs.sh Pulls binary artifacts from remote repository. -+--lib/ Pre-compiled libraries for the build. -+--src/ All sources. - +---/library Scala Standard Library. - +---/reflect Scala Reflection. - +---/compiler Scala Compiler. - +---/eclipse Eclipse project files. - +---/intellij IntelliJ project templates. ++--build.sbt The main sbt build script ++--build.xml The deprecated Ant build script ++--pull-binary-libs.sh Pulls binary artifacts from remote repository, used by build scripts ++--lib/ Pre-compiled libraries for the build ++--src/ All sources + +---/library Scala Standard Library + +---/reflect Scala Reflection + +---/compiler Scala Compiler + +---/eclipse Eclipse project files + +---/intellij IntelliJ project templates ++--spec/ The Scala language specification +--scripts/ Scripts for the CI jobs (including building releases) -+--test/ The Scala test suite. -+--build/ [Generated] Build products output directory for ant. -+--dist/ [Generated] The destination folder for Scala distributions. ++--test/ The Scala test suite + +---/files Partest tests + +---/junit JUnit tests ++--build/ [Generated] Build output directory ``` -# How we roll +# Get Ready to Contribute ## Requirements -You'll need a Java SDK. The baseline version is 6 for 2.11.x, 8 for -2.12.x. (It's also possible to use a later SDK for local development, -but the CI will verify against the baseline version.) - -You'll also need Apache Ant (version 1.9.0 or above) and curl (for `./pull-binary-libs.sh`). - -Mac OS X and Linux work. Windows may work if you use Cygwin. (Community help with keeping the build working on Windows is appreciated.) - -## Git Hygiene - -As git history is forever, we take great pride in the quality of the commits we merge into the repository. The title of your commit will be read hundreds (of thousands? :-)) of times, so it pays off to spend just a little bit more time to polish it, making it descriptive and concise. Please take a minute to read the advice [most projects agree on](https://github.com/erlang/otp/wiki/Writing-good-commit-messages), and stick to 72 or fewer characters for the first line, wrapping subsequent ones at 80 (at most). - -When not sure how to formulate your commit message, imagine you're writing a bullet item for the next release notes, or describing what the commit does to the code base (use active verbs in the present tense). When your commit title is featured in the next release notes, it will be read by a lot of curious Scala users, looking for the latest improvements. Satisfy their thirst for information with as few words as possible! Also, a commit should convey clearly to your (future) fellow contributors what it does to the code base. - -Writing the commit message is a great sanity check that the commit is of the right size. If it does too many things, the description will be unwieldy and tedious to write. Chop it up (`git add -u --patch` and `git rebase` are your friends) and simplify! - -To pinpoint bugs, we often use git bisect, which is only effective when we can count on each commit building (and passing the test suite). Thus, the CI bot enforces this. Please rebase your development history into a sensible list of self-contained commits that tell the story of your bug fix or improvement. Carve them up so that the riskier bits can be reverted independently. Keep changes focussed by splitting out cleanups from refactorings from actual changes to the logic. - -This facilitates reviewing: a commit that reformats code can be judged quickly not to affect anything, so we can focus on the meat of the PR. It also helps when merging between long-running branches, reducing conflicts (or providing at least a limited scope for each one). - -Please do not @-mention anyone in the commit message -- that's what the PR description and comments are for. Every time a commit is shuffled through github (in a merge in some fork, say), every @-mention results in an email to that person (the core team treats them as personal email, straight to their inbox, so please don't flood us :-)). - - -## Reviews - -Please consider nominating a reviewer for your PR in the PR's description or a comment. If unsure, not to worry -- the core team will assign one for you. - -Your reviewer is also your mentor, who will help you rework your PR so that it meets our requirements. We strive to give timely feedback, and apologize for those times when we are overwhelmed by the volume of contributions. Please feel free to ping us. You are entitled to regular progress updates and at least a quick assessment of feasibility of a bigger PR. - -To help you plan your contributions, we communicate our plans on a regular basis on scala-internals, and deadlines are tracked as due dates for [GitHub milestones](https://github.com/scala/scala/milestones). - -## Reviewing - -Once you've gained some experience with the code base and the process, the next step is to review the contributions of others. - -The main goal of this whole process is to ensure the health of the Scala project by improving the quality of the code base, the documentation, as well as this process itself. Thank you for doing your part! - -## [Labels](https://github.com/scala/scala/labels) - -Label | Description ---------------- | ----------- -`reviewed` | automatically added by scabot when a comment prefixed with LGTM is posted -`welcome` | reviewer / queue curator adds to welcome someone's first PR (for highlighting in the release notes) -`release-notes` | reviewer / queue curator adds to make sure this PR is highlighted in the release notes -`on-hold` | added when this PR should not yet be merged, even though CI is green - -### Tips & Tricks -Once the `publish-core` task has completed on a commit, you can try it out in sbt as follows: +You need the following tools: + - A Java SDK. The baseline version is 6 for 2.11.x, 8 for 2.12.x. It's possible + to use a later SDK for local development, but the CI will verify against the baseline + version. + - sbt, we recommend the [sbt-extras](https://github.com/paulp/sbt-extras) runner + script. It provides sensible default jvm options (stack and heap size). + - curl (for `./pull-binary-libs.sh`, used by the sbt / ant build). + - Apache Ant (version 1.9.3 or above) if you need to use the (deprecated) ant build. + +Mac OS X and Linux work. Windows may work if you use Cygwin. Community help with keeping +the build working on Windows is appreciated. + +## Build Setup + +### Basics + +Scala is built in layers, where each layer is a complete Scala compiler and library. +Here is a short description of the layers, from bottom to top: + + - `starr`: the stable reference Scala release. We use an official release of + Scala (specified by `starr.version` in [versions.properties](versions.properties)), + downloaded from the Central Repository. + - `locker` (deprecated, only in ant): an intermediate layer that existed in the + ant build to perform a bootstrap. + - `quick`: the development layer which is incrementally built when working on + changes in the compiler or library. + - `strap` (deprecated, only in ant) : a test layer used to check stability of + the build. + +The sbt build uses `starr` to build `quick`. This is sufficient for most development +scenarios: changes to the library or the compiler can be tested by running the `quick` +Scala (see below for how to do that). + +However, a full build of Scala (a *bootstrap*, as performed by our CI) requires two +layers. This guarantees that every Scala version can build itself. If you change the +code generation part of the Scala compiler, your changes will only reflect in the +bytecode of the library and compiler after a bootstrap. See below for how to create +a bootstrap build locally. + +### Using the Sbt Build + +Core commands: + - `compile` compiles all sub-projects (library, reflect, compiler, scaladoc, etc) + - `scala` / `scalac` run the REPL / compiler directly from sbt (accept options / + arguments) + - `dist/mkBin` generates runner scripts (`scala`, `scalac`, etc) in `build/quick/bin` + - `dist/mkPack` creates a build in the Scala distribution format in `build/pack` + - `test` runs the JUnit test, `testOnly *immutable.ListTest` runs a subset + - `partest` runs partest tests (accepts options, try `partest --help`) + - `publishLocal` publishes a distribution locally (can be used as `scalaVersion` in + other sbt projects) + - Optionally `set VersionUtil.baseVersionSuffix in Global := "abcd123-SNAPSHOT"` + where `abcd123` is the git hash of the revision being published. You can also + use something custom like `"mypatch"`. This changes the version number from + `2.12.0-SNAPSHOT` to something more stable (`2.12.0-abcd123-SNAPSHOT`). + - Optionally `set publishArtifact in (Compile, packageDoc) in ThisBuild := false` + to skip generating / publishing API docs (speeds up the process). + +#### Sandbox + +We recommend to keep local test files in the `sandbox` directory which is listed in +the `.gitignore` of the Scala repo. + +#### Incremental Compilation + +Note that sbt's incremental compilation is often too coarse for the Scala compiler +codebase and re-compiles too many files, resulting in long build times (check +[sbt#1104](https://github.com/sbt/sbt/issues/1104) for progress on that front). In the +meantime you can: + - Enable "ant mode" in which sbt only re-compiles source files that were modified. + Create a file `local.sbt` containing the line `(incOptions in ThisBuild) := (incOptions in ThisBuild).value.withNameHashing(false).withAntStyle(true)`. + Add an entry `local.sbt` to your `~/.gitignore`. + - Use IntelliJ IDEA for incremental compiles (see [IDE Setup](#ide-setup) below) - its + incremental compiler is a bit less conservative, but usually correct. + +#### Local Bootstrap Build + +To perform a bootstrap using sbt + - first a build is published either locally or on a temporary repository, + - then a separate invocation of sbt (using the previously built version as `starr`) + is used to build / publish the actual build. + +Assume the current `starr` version is `2.12.0-M4` (defined in +[versions.properties](versions.properties)) and the current version is `2.12.0-SNAPSHOT` +(defined in [build.sbt](build.sbt)). To perform a local bootstrap: + - Run `publishLocal` (you may want to specify a custom version suffix and skip + generating API docs, see above). + - Quit sbt and start a new sbt instance using `sbt -Dstarr.version=` where + `` is the version number you published locally. + - If the version number you published is not binary compatible with the current + `starr`, `set every scalaBinaryVersion := "2.12.0-M4"`. This is not required if + the version you published locally is binary compatible, i.e., if the current + `starr` is a 2.12.x release and not a milestone / RC. + +The last step is required to resolve modules (scala-xml, scala-partest, etc). It +assumes that the module releases for the current `starr` work (in terms of binary +compatibility) with the local starr that you published locally. A full bootstrap +requires re-building the all the modules. On our CI this is handled by the +[bootstrap](scripts/jobs/integrate/bootstrap) script, but it (currently) cannot +be easily executed locally. + +### IDE Setup + +You may use IntelliJ IDEA ([src/intellij/README.md](src/intellij/README.md)) or the +Scala IDE for Eclipse (see [src/eclipse/README.md](src/eclipse/README.md)). + +In order to use IntelliJ's incremental compiler: + - run `dist/mkBin` in sbt to get a build and the runner scripts in `build/quick/bin` + - run "Build" - "Make Project" in IntelliJ + +Now you can edit and build in IntelliJ and use the scripts (compiler, REPL) to +directly test your changes. You can also run the `scala`, `scalac` and `partest` +commands in sbt. Enable "ant mode" (explained above) to prevent sbt's incremental +compiler from re-compiling (too many) files before each `partest` invocation. + +# Coding Guidelines + +Our guidelines for contributing are explained in [CONTRIBUTING.md](CONTRIBUTING.md). +It contains useful information on our coding standards, testing, documentation, how +we use git and GitHub and how to get your code reviewed. + +You may also want to check out the following resources: + - The ["Scala Hacker Guide"](http://scala-lang.org/contribute/hacker-guide.html) + covers some of the same ground as this README, but in greater detail and in a more + tutorial style, using a running example. + - [Scala documentation site](http://docs.scala-lang.org) + +# Scala CI + +Once you submit a PR your commits will are automatically tested by the Scala CI. + +If you see a spurious build failure, you can post `/rebuild` as a PR comment. +The [scabot README](https://github.com/scala/scabot) lists all available commands. + +If you'd like to test your patch before having everything polished for review, +feel free to submit a PR and add the `WIP` label. In case your WIP branch contains +a large number of commits (that you didn't clean up / squash yet for review), +consider adding `[ci: last-only]` to the PR title. That way only the last commit +will be tested, saving some energy and CI-resources. Note that inactive WIP PRs +will be closed eventually, which does not mean the change is being rejected. + +CI performs a full bootstrap. The first task, `validate-publish-core`, publishes +a build of your commit to the temporary repository +https://scala-ci.typesafe.com/artifactory/scala-pr-validation-snapshots. +Note that this build is not yet bootstrapped, its bytecode is built using the +current `starr`. The version number is `2.12.0-abcd123-SNAPSHOT` where `abcd123` +is the commit hash. + +You can use Scala builds in the validation repository locally by adding a resolver +and specifying the corresponding `scalaVersion`: ``` $ sbt - > set resolvers += "pr" at "https://scala-ci.typesafe.com/artifactory/scala-pr-validation-snapshots/" -> set scalaVersion := "--SNAPSHOT" +> set scalaVersion := "2.12.0-abcd123-SNAPSHOT" > console ``` -Here, `` is the milestone targeted by the PR (e.g., 2.11.6), and `` is the 7-character sha (the format used by GitHub on the web). - -## IDE Setup -### Eclipse -See [src/eclipse/README.md](src/eclipse/README.md). - -### IntelliJ 15 -See [src/intellij/README.md](src/intellij/README.md). - -## Building with sbt (EXPERIMENTAL) - -The experimental sbt-based build definition has arrived! Run `sbt package` -to build the compiler. You can run `sbt test` to run unit (JUnit) tests. -Use `sbt test/it:test` to run integration (partest) tests. - -We would like to migrate to sbt build as quickly as possible. If you would -like to help please use the scala-internals mailing list to discuss your -ideas and coordinate your effort with others. - -## Building with Ant +Note that the scala modules are currently not built / published against the +tested version during CI validation. -NOTE: we are working on migrating the build to sbt. +## Nightly Builds -If you are behind a HTTP proxy, include -[`ANT_ARGS=-autoproxy`](https://ant.apache.org/manual/proxy.html) in -your environment. +The Scala CI builds nightly download releases (including all modules) and publishes +them to the following locations: + - [2.12.x](http://www.scala-lang.org/files/archive/nightly/2.12.x/?C=M;O=D) + - [2.11.x](http://www.scala-lang.org/files/archive/nightly/2.11.x/?C=M;O=A) -Run `ant build-opt` to build an optimized version of the compiler. -Verify your build using `ant test-opt`. +The CI also publishes nightly API docs: + - [2.12.x](http://www.scala-lang.org/files/archive/nightly/2.12.x/api/?C=M;O=D) + - [symlink to the latest](http://www.scala-lang.org/files/archive/nightly/2.12.x/api/2.12.x/) + - [2.11.x](http://www.scala-lang.org/files/archive/nightly/2.11.x/api/?C=M;O=D) + - [symlink to the latest](http://www.scala-lang.org/files/archive/nightly/2.11.x/api/2.11.x/) -The Scala build system is based on Apache Ant. Most required pre-compiled -libraries are part of the repository (in 'lib/'). The following however is -assumed to be installed on the build machine: TODO +Note that we currently don't publish nightly (or SNAPSHOT) builds in maven or ivy +format to any repository. You can track progress on this front at +[scala-jenkins-infra#133](https://github.com/scala/scala-jenkins-infra/issues/133) +and [scala-dev#68](https://github.com/scala/scala-dev/issues/68). -### Ant Tips and tricks +## Scala CI Internals -Here are some common commands. Most ant targets offer a `-opt` variant that runs under `-optimise` (CI runs the -optimize variant). - -Command | Description ------------------------ | ----------- -`./pull-binary-libs.sh` | downloads all binary artifacts associated with this commit. -`ant -p` | prints out information about the commonly used ant targets. -`ant` or `ant build` | A quick compilation (to `build/quick`) of your changes using the locker compiler. -`ant dist` | builds a distribution in 'dists/latest'. -`ant all.clean` | removes all build files and all distributions. - -A typical debug cycle incrementally builds quick, then uses it to compile and run the file -`sandbox/test.scala` as follows: - - - `ant && build/quick/bin/scalac -d sandbox sandbox/test.scala && build/quick/bin/scala -cp sandbox Test` - -We typically alias `build/quick/bin/scalac -d sandbox` to `qsc` and `build/quick/bin/scala -cp sandbox` to `qs` in our shell. - -`ant test-opt` tests that your code is working and fit to be committed: - - - Runs the test suite and bootstrapping test on quick. - - You can run the suite only (skipping strap) with `ant test.suite`. - -`ant docs` generates the HTML documentation for the library from the sources using the scaladoc tool in quick. -Note: on most machines this requires more heap than is allocated by default. You can adjust the parameters with `ANT_OPTS`. Example command line: - -```sh -ANT_OPTS="-Xms512M -Xmx2048M -Xss1M -XX:MaxPermSize=128M" ant docs -``` +The Scala CI runs as a Jenkins instance on [scala-ci.typesafe.com](https://scala-ci.typesafe.com/), +configured by a chef cookbook at [scala/scala-jenkins-infra](https://github.com/scala/scala-jenkins-infra). -### Bootstrapping concepts -NOTE: This is somewhat outdated, but the ideas still hold. +The build bot that watches PRs, triggers testing builds and applies the "reviewed" label +after an LGTM comment is in the [scala/scabot](https://github.com/scala/scabot) repo. -In order to guarantee the bootstrapping of the Scala compiler, the ant build -compiles Scala in layers. Each layer is a complete compiled Scala compiler and library. -A superior layer is always compiled by the layer just below it. Here is a short -description of the four layers that the build uses, from bottom to top: +## Community Build - - `starr`: the stable reference Scala release. We use an official version of Scala (specified by `starr.version` in `versions.properties`), downloaded from the Central Repository. - - `locker`: the local reference which is compiled by starr and is the work compiler in a typical development cycle. Add `locker.skip=true` to `build.properties` to skip this step and speed up development when you're not changing code generation. In any case, after it has been built once, it is “frozen” in this state. Updating it to fit the current source code must be explicitly requested (`ant locker.unlock`). - - `quick`: the layer which is incrementally built when testing changes in the compiler or library. This is considered an actual new version when locker is up-to-date in relation to the source code. - - `strap`: a test layer used to check stability of the build. +The community build is a central element for testing Scala releases. A community +build can be launched for any Scala revision / commit. It first builds the Scala +library and compiler and then uses that Scala version to build a large number of +open-source projects from source. -For each layer, the Scala library is compiled first and the compiler next. -That means that any changes in the library can immediately be used in the -compiler without an intermediate build. On the other hand, if building the -library requires changes in the compiler, a new locker must be built if -bootstrapping is still possible, or a new starr if it is not. +Community builds run on the Scala Jenkins instance, the jobs are named +`..-integrate-community-build`. The community build definitions specifying which +projects are built are in the +[scala/community-builds](https://github.com/scala/community-builds) repo. diff --git a/src/intellij/README.md b/src/intellij/README.md index c311afda9c16..41fef0418362 100644 --- a/src/intellij/README.md +++ b/src/intellij/README.md @@ -1,40 +1,81 @@ -# Building Scala in IntelliJ IDEA - -## Requirements +# Developing Scala in IntelliJ IDEA Use the latest IntelliJ release and install the Scala plugin from within the IDE. -## Initial setup +## Initial Setup To create the IntelliJ project files: - Run `sbt intellij` - Open `src/intellij/scala.ipr` in IntelliJ - - In `File` → `Project Structure` → `Project` → `Project SDK`, create an SDK entry named "1.6" containing the Java 1.6 SDK + - In `File` → `Project Structure` → `Project` → `Project SDK`, create an SDK entry + named "1.8" containing the Java 1.8 SDK (1.6 if you're on the Scala the 2.11.x branch) -The project files are created by as copies of the `.SAMPLE` files, which are under version control. -The actual IntelliJ project files are in `.gitignore` so that local changes are ignored. +The project files are created as copies of the `.SAMPLE` files, which are under version +control. The actual IntelliJ project files are in `.gitignore` so that local changes +are ignored. ## Dependencies For every module in the IntelliJ project there is a corresponding `-deps` library, for exmaple `compiler-deps` provides `ant.jar` for the compiler codebase. The `.jar` files in these `-deps` libraries can be easily kept up-to-date by running `sbt intellij` again. -This is necessary whenever the dependencies in the sbt build change, for example when the STARR version is updated. +This is necessary whenever the dependencies in the sbt build change, for example when the `starr` version is updated. Note that this command only patches the dependency lists, all other settings in the IntelliJ project definition are unchanged. To overwrite the project definition files by copying the `.SAMPLE` files again run `sbt intellijFromSample`. -## Usage +## Switching Branches + +The 2.12.x branch contains IntelliJ module files for `actors` and `forkjoin` even though these modules only exist in 2.11.x. +This allows using the same IntelliJ project files when switching to the 2.11.x branch (without causing any issues while working on 2.12.x). + +When switching between 2.11.x and 2.12.x, make sure to run `sbt intellij`. +Note that the `Project SDK` is not updated in this process. +If you want to use the Java 1.6 SDK while working on 2.11.x you need to change it manually (`File` → `Project Structure` → `Project` → `Project SDK`). + +If you switch between 2.11.x and 2.12.x often, it makes sense to have a separate clone +of the repository for each branch. + +## Incremental Compilation + +Run `Build` → `Make Project` to build all modules of the Scala repository (library, +compiler, etc). Note that compilation IntelliJ is performed in a single pass (no +bootstrap), like the sbt build. + +Note that the output directory when compiling in IntelliJ is the same as for the +sbt and (deprecated) ant builds. This allows building incrementally in IntelliJ +and directly use the changes using the command-line scripts in `build/quick/bin/`. + +## Running JUnit Tests + +JUnit tests can be executed by right-clicking on a test class or test method and +selecting "Run" or "Debug". The debugger will allow you to stop at breakpoints +within the Scala library. + +It is possible to invoke the Scala compiler from a JUnit test (passing the source +code as a string) and inspect the generated bytecode, see for example +`scala.issues.BytecodeTest`. Debugging such a test is an easy way to stop at +breakpoints within the Scala compiler. + +## Running the Compiler and REPL + +You can create run/debug configurations to run the compiler and REPL directly within +IntelliJ, which might accelerate development and debugging of the the compiler. -Compiling, running, JUnit tests and debugging should all work. -You can work on the compiler, the standard library, and other components as well. +To debug the Scala codebase you can also use "Remote" debug configuration and pass +the corresponding arguments to the jvm running the compiler / program. -Note that compilation within IntelliJ is performed in a single pass. -The code is compiled using the "STARR" (stable reference) compiler, as specified by `starr.version` in `versions.properties`. -This is consistent with the sbt build. +To run the compiler create an "Application" configuration with + - Main class: `scala.tools.nsc.Main` + - Program arguments: `-usejavacp -cp sandbox -d sandbox sandbox/Test.scala` + - Working directory: the path of your checkout + - Use classpath of module: `compiler` -Note that the output directory when compiling in IntelliJ is the same as for the sbt build. -This allows building incrementally in IntelliJ and directly use the changes using the command-line scripts in `build/quick/bin/`. +To run the REPL create an "Application" configuration with + - Main class: `scala.tools.nsc.MainGenericRunner` + - Program arguments: `-usejavacp` + - Working directory: the path of your checkout + - Use classpath of module: `repl` ## Updating the `.SAMPLE` files From 214ea82573624bffb4d0f16f3e5c49f9370ba7a7 Mon Sep 17 00:00:00 2001 From: Steve Robinson Date: Sat, 27 Feb 2016 09:13:45 -0800 Subject: [PATCH 028/153] SI-9656 Range.toString distinguishes Numeric step For Range and NumericRange, toString will indicate the step if it is not 1. Additionally, indicate empty ranges and ranges which are not "exact". For a "mapped" range, used by `Range.Double`, toString includes the underlying range and the simple type of the step (to distinguish Double from BigDecimal). --- .../collection/immutable/NumericRange.scala | 14 ++++-- .../scala/collection/immutable/Range.scala | 17 ++++---- test/files/jvm/serialization-new.check | 8 ++-- test/files/jvm/serialization.check | 8 ++-- test/files/run/t9656.check | 14 ++++++ test/files/run/t9656.scala | 43 +++++++++++++++++++ 6 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 test/files/run/t9656.check create mode 100644 test/files/run/t9656.scala diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala index c8d751925441..fdf50960a383 100644 --- a/src/library/scala/collection/immutable/NumericRange.scala +++ b/src/library/scala/collection/immutable/NumericRange.scala @@ -161,6 +161,12 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { override def isEmpty = underlyingRange.isEmpty override def apply(idx: Int): A = fm(underlyingRange(idx)) override def containsTyped(el: A) = underlyingRange exists (x => fm(x) == el) + + override def toString = { + def simpleOf(x: Any): String = x.getClass.getName.split("\\.").last + val stepped = simpleOf(underlyingRange.step) + s"${super.toString} (using $underlyingRange of $stepped)" + } } } @@ -250,9 +256,11 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { super.equals(other) } - override def toString() = { - val endStr = if (length > Range.MAX_PRINT) ", ... )" else ")" - take(Range.MAX_PRINT).mkString("NumericRange(", ", ", endStr) + override def toString = { + val empty = if (isEmpty) "empty " else "" + val preposition = if (isInclusive) "to" else "until" + val stepped = if (step == 1) "" else s" by $step" + s"${empty}NumericRange $start $preposition $end$stepped" } } diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index d3fe367e5035..6eaf404fe8e2 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -396,22 +396,20 @@ extends scala.collection.AbstractSeq[Int] case _ => super.equals(other) } - /** Note: hashCode can't be overridden without breaking Seq's - * equals contract. - */ - override def toString() = { - val endStr = - if (numRangeElements > Range.MAX_PRINT || (!isEmpty && numRangeElements < 0)) ", ... )" else ")" - take(Range.MAX_PRINT).mkString("Range(", ", ", endStr) + /* Note: hashCode can't be overridden without breaking Seq's equals contract. */ + + override def toString = { + val preposition = if (isInclusive) "to" else "until" + val stepped = if (step == 1) "" else s" by $step" + val prefix = if (isEmpty) "empty " else if (!isExact) "inexact " else "" + s"${prefix}Range $start $preposition $end$stepped" } } /** A companion object for the `Range` class. */ object Range { - private[immutable] val MAX_PRINT = 512 // some arbitrary value - /** Counts the number of range elements. * @pre step != 0 * If the size of the range exceeds Int.MaxValue, the @@ -514,6 +512,7 @@ object Range { // we offer a partially constructed object. class Partial[T, U](f: T => U) { def by(x: T): U = f(x) + override def toString = "Range requires step" } // Illustrating genericity with Int Range, which should have the same behavior diff --git a/test/files/jvm/serialization-new.check b/test/files/jvm/serialization-new.check index 1c5dd4828bea..ca91ec107384 100644 --- a/test/files/jvm/serialization-new.check +++ b/test/files/jvm/serialization-new.check @@ -97,12 +97,12 @@ x = Queue(a, b, c) y = Queue(a, b, c) x equals y: true, y equals x: true -x = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) -y = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) +x = Range 0 until 10 +y = Range 0 until 10 x equals y: true, y equals x: true -x = NumericRange(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) -y = NumericRange(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) +x = NumericRange 0 until 10 +y = NumericRange 0 until 10 x equals y: true, y equals x: true x = Map(1 -> A, 2 -> B, 3 -> C) diff --git a/test/files/jvm/serialization.check b/test/files/jvm/serialization.check index 1c5dd4828bea..ca91ec107384 100644 --- a/test/files/jvm/serialization.check +++ b/test/files/jvm/serialization.check @@ -97,12 +97,12 @@ x = Queue(a, b, c) y = Queue(a, b, c) x equals y: true, y equals x: true -x = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) -y = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) +x = Range 0 until 10 +y = Range 0 until 10 x equals y: true, y equals x: true -x = NumericRange(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) -y = NumericRange(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) +x = NumericRange 0 until 10 +y = NumericRange 0 until 10 x equals y: true, y equals x: true x = Map(1 -> A, 2 -> B, 3 -> C) diff --git a/test/files/run/t9656.check b/test/files/run/t9656.check new file mode 100644 index 000000000000..03e3ff3b5fcb --- /dev/null +++ b/test/files/run/t9656.check @@ -0,0 +1,14 @@ +Range 1 to 10 +Range 1 to 10 +inexact Range 1 to 10 by 2 +Range 1 to 10 by 3 +inexact Range 1 until 10 by 2 +Range 100 to 100 +empty Range 100 until 100 +NumericRange 1 to 10 +NumericRange 1 to 10 by 2 +NumericRange 0.1 until 1.0 by 0.1 +NumericRange 0.1 until 1.0 by 0.1 +NumericRange 0.1 until 1.0 by 0.1 (using NumericRange 0.1 until 1.0 by 0.1 of BigDecimal) +NumericRange 0 days until 10 seconds by 1 second +empty NumericRange 0 days until 0 days by 1 second diff --git a/test/files/run/t9656.scala b/test/files/run/t9656.scala new file mode 100644 index 000000000000..373271955340 --- /dev/null +++ b/test/files/run/t9656.scala @@ -0,0 +1,43 @@ + +import scala.math.BigDecimal + +object Test extends App { + println(1 to 10) + println(1 to 10 by 1) + println(1 to 10 by 2) + println(1 to 10 by 3) + println(1 until 10 by 2) + println(100 to 100) + println(100 until 100) + + println(1L to 10L) + println(1L to 10L by 2) + + // want to know if this is BigDecimal or Double stepping by BigDecimal + println(0.1 until 1.0 by 0.1) + println(Range.BigDecimal(BigDecimal("0.1"), BigDecimal("1.0"), BigDecimal("0.1"))) + println(Range.Double(0.1, 1.0, 0.1)) + + import concurrent.duration.{SECONDS => Seconds, _}, collection.immutable.NumericRange + implicit val `duration is integerish`: math.Integral[FiniteDuration] = new math.Integral[FiniteDuration] { + def quot(x: scala.concurrent.duration.FiniteDuration,y: scala.concurrent.duration.FiniteDuration): scala.concurrent.duration.FiniteDuration = ??? + def rem(x: scala.concurrent.duration.FiniteDuration,y: scala.concurrent.duration.FiniteDuration): scala.concurrent.duration.FiniteDuration = ??? + + // Members declared in scala.math.Numeric + def fromInt(x: Int): scala.concurrent.duration.FiniteDuration = Duration(x, Seconds) + def minus(x: scala.concurrent.duration.FiniteDuration,y: scala.concurrent.duration.FiniteDuration): scala.concurrent.duration.FiniteDuration = ??? + def negate(x: scala.concurrent.duration.FiniteDuration): scala.concurrent.duration.FiniteDuration = ??? + def plus(x: scala.concurrent.duration.FiniteDuration,y: scala.concurrent.duration.FiniteDuration): scala.concurrent.duration.FiniteDuration = ??? + def times(x: scala.concurrent.duration.FiniteDuration,y: scala.concurrent.duration.FiniteDuration): scala.concurrent.duration.FiniteDuration = ??? + def toDouble(x: scala.concurrent.duration.FiniteDuration): Double = ??? + def toFloat(x: scala.concurrent.duration.FiniteDuration): Float = ??? + def toInt(x: scala.concurrent.duration.FiniteDuration): Int = toLong(x).toInt + def toLong(x: scala.concurrent.duration.FiniteDuration): Long = x.length + + // Members declared in scala.math.Ordering + def compare(x: scala.concurrent.duration.FiniteDuration,y: scala.concurrent.duration.FiniteDuration): Int = + x.compare(y) + } + println(NumericRange(Duration.Zero, Duration(10, Seconds), Duration(1, Seconds))) + println(NumericRange(Duration.Zero, Duration.Zero, Duration(1, Seconds))) +} From 3cddeaa525fd6fe9860a27019fdf484297a8d3dd Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sun, 13 Sep 2015 17:22:11 -0700 Subject: [PATCH 029/153] SI-7916: ScriptEngine support Refactor the ScriptEngine support to an adaptor atop the IMain API. Allow references to resolve to context attributes. (The attributes must be defined at compilation time, though they may resolve to updated values at evaluation time.) This means that attributes are not bound statically in REPL history. In particular, we forgo the trick of binding attributes named "name: Type" as typed values. Instead, an `x` bound in dynamic context is injected into the script as a dynamic selection `$ctx.x` where `ctx` performs the look-up in the script context. When a compiled script is re-evaluated, a new instance of the script class is created and defined symbols are rebound. The context stdout writer is handled with `Console.withOut`, with bytes decoded using the default charset. Compilation errors are thrown as ScriptException with the first reported error. This commit doesn't attempt dynamic selection from objects in context. Currently, script must cast. --- build.xml | 2 +- .../scala/tools/nsc/interpreter/IMain.scala | 203 +++-------- .../tools/nsc/interpreter/Scripted.scala | 343 ++++++++++++++++++ .../scala/tools/nsc/interpreter/package.scala | 2 +- test/files/run/repl-serialization.scala | 2 +- test/files/run/t1500.scala | 2 +- test/files/run/t7843-jsr223-service.check | 2 - test/files/run/t7843-jsr223-service.scala | 8 - test/files/run/t7933.check | 2 - test/files/run/t7933.scala | 11 - .../tools/nsc/interpreter/ScriptedTest.scala | 83 +++++ 11 files changed, 471 insertions(+), 189 deletions(-) create mode 100644 src/repl/scala/tools/nsc/interpreter/Scripted.scala delete mode 100644 test/files/run/t7843-jsr223-service.check delete mode 100644 test/files/run/t7843-jsr223-service.scala delete mode 100644 test/files/run/t7933.check delete mode 100644 test/files/run/t7933.scala create mode 100644 test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala diff --git a/build.xml b/build.xml index 8790bf637d3f..778bcc561b14 100644 --- a/build.xml +++ b/build.xml @@ -1163,7 +1163,7 @@ TODO: - + diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 8c91242b36ac..a42a12a6fc5c 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -20,7 +20,6 @@ import scala.tools.nsc.typechecker.{StructuredTypeStrings, TypeStrings} import scala.tools.nsc.util._ import ScalaClassLoader.URLClassLoader import scala.tools.nsc.util.Exceptional.unwrap -import javax.script.{AbstractScriptEngine, Bindings, Compilable, CompiledScript, ScriptContext, ScriptEngine, ScriptEngineFactory, ScriptException} import java.net.URL import scala.tools.util.PathResolver @@ -56,10 +55,11 @@ import scala.tools.util.PathResolver * @author Moez A. Abdel-Gawad * @author Lex Spoon */ -class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Settings, protected val out: JPrintWriter) extends AbstractScriptEngine with Compilable with Imports with PresentationCompilation { +class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends Imports with PresentationCompilation { imain => - setBindings(createBindings, ScriptContext.ENGINE_SCOPE) + def this(initialSettings: Settings) = this(initialSettings, IMain.defaultOut) + object replOutput extends ReplOutput(settings.Yreploutdir) { } @deprecated("Use replOutput.dir instead", "2.11.0") @@ -104,13 +104,6 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set finally if (!saved) settings.nowarn.value = false } - /** construct an interpreter that reports to Console */ - def this(settings: Settings, out: JPrintWriter) = this(null, settings, out) - def this(factory: ScriptEngineFactory, settings: Settings) = this(factory, settings, new NewLinePrintWriter(new ConsoleWriter, true)) - def this(settings: Settings) = this(settings, new NewLinePrintWriter(new ConsoleWriter, true)) - def this(factory: ScriptEngineFactory) = this(factory, new Settings()) - def this() = this(new Settings()) - // the expanded prompt but without color escapes and without leading newline, for purposes of indenting lazy val formatting = Formatting.forPrompt(replProps.promptText) lazy val reporter: ReplReporter = new ReplReporter(this) @@ -464,7 +457,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set pos } - private[interpreter] def requestFromLine(line: String, synthetic: Boolean): Either[IR.Result, Request] = { + private[interpreter] def requestFromLine(line: String, synthetic: Boolean = false): Either[IR.Result, Request] = { val content = line val trees: List[global.Tree] = parse(content) match { @@ -559,77 +552,8 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set */ def interpret(line: String): IR.Result = interpret(line, synthetic = false) def interpretSynthetic(line: String): IR.Result = interpret(line, synthetic = true) - def interpret(line: String, synthetic: Boolean): IR.Result = compile(line, synthetic) match { - case Left(result) => result - case Right(req) => new WrappedRequest(req).loadAndRunReq - } - - private def compile(line: String, synthetic: Boolean): Either[IR.Result, Request] = { - if (global == null) Left(IR.Error) - else requestFromLine(line, synthetic) match { - case Left(result) => Left(result) - case Right(req) => - // null indicates a disallowed statement type; otherwise compile and - // fail if false (implying e.g. a type error) - if (req == null || !req.compile) Left(IR.Error) else Right(req) - } - } - - var code = "" - var bound = false - def compiled(script: String): CompiledScript = { - if (!bound) { - quietBind("engine" -> this.asInstanceOf[ScriptEngine]) - bound = true - } - val cat = code + script - compile(cat, false) match { - case Left(result) => result match { - case IR.Incomplete => { - code = cat + "\n" - new CompiledScript { - def eval(context: ScriptContext): Object = null - def getEngine: ScriptEngine = IMain.this - } - } - case _ => { - code = "" - throw new ScriptException("compile-time error") - } - } - case Right(req) => { - code = "" - new WrappedRequest(req) - } - } - } - - private class WrappedRequest(val req: Request) extends CompiledScript { - var recorded = false - - /** In Java we would have to wrap any checked exception in the declared - * ScriptException. Runtime exceptions and errors would be ok and would - * not need to be caught. So let us do the same in Scala : catch and - * wrap any checked exception, and let runtime exceptions and errors - * escape. We could have wrapped runtime exceptions just like other - * exceptions in ScriptException, this is a choice. - */ - @throws[ScriptException] - def eval(context: ScriptContext): Object = { - val result = req.lineRep.evalEither match { - case Left(e: RuntimeException) => throw e - case Left(e: Exception) => throw new ScriptException(e) - case Left(e) => throw e - case Right(result) => result.asInstanceOf[Object] - } - if (!recorded) { - recordRequest(req) - recorded = true - } - result - } - - def loadAndRunReq = classLoader.asContext { + def interpret(line: String, synthetic: Boolean): IR.Result = { + def loadAndRunReq(req: Request) = classLoader.asContext { val (result, succeeded) = req.loadAndRun /** To our displeasure, ConsoleReporter offers only printMessage, @@ -654,12 +578,32 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set } } - def getEngine: ScriptEngine = IMain.this + compile(line, synthetic) match { + case Left(result) => result + case Right(req) => loadAndRunReq(req) + } + } + + // create a Request and compile it + private[interpreter] def compile(line: String, synthetic: Boolean): Either[IR.Result, Request] = { + if (global == null) Left(IR.Error) + else requestFromLine(line, synthetic) match { + case Right(null) => Left(IR.Error) // disallowed statement type + case Right(req) if !req.compile => Left(IR.Error) // compile error + case ok @ Right(req) => ok + case err @ Left(result) => err + } } /** Bind a specified name to a specified value. The name may * later be used by expressions passed to interpret. * + * A fresh `ReadEvalPrint`, which defines a `line` package, is used to compile + * a custom `eval` object that wraps the bound value. + * + * If the bound value is successfully installed, then bind the name + * by interpreting `val name = $line42.$eval.value`. + * * @param name the variable name to bind * @param boundType the type of the variable, as a string * @param value the object value to bind to it @@ -667,22 +611,22 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set */ def bind(name: String, boundType: String, value: Any, modifiers: List[String] = Nil): IR.Result = { val bindRep = new ReadEvalPrint() - bindRep.compile(""" - |object %s { - | var value: %s = _ - | def set(x: Any) = value = x.asInstanceOf[%s] + bindRep.compile(s""" + |object ${bindRep.evalName} { + | var value: $boundType = _ + | def set(x: Any) = value = x.asInstanceOf[$boundType] |} - """.stripMargin.format(bindRep.evalName, boundType, boundType) - ) + """.stripMargin + ) bindRep.callEither("set", value) match { case Left(ex) => repldbg("Set failed in bind(%s, %s, %s)".format(name, boundType, value)) repldbg(util.stackTraceString(ex)) IR.Error - case Right(_) => - val line = "%sval %s = %s.value".format(modifiers map (_ + " ") mkString, name, bindRep.evalPath) - repldbg("Interpreting: " + line) + val mods = if (modifiers.isEmpty) "" else modifiers.mkString("", " ", " ") + val line = s"${mods}val $name = ${ bindRep.evalPath }.value" + repldbg(s"Interpreting: $line") interpret(line) } } @@ -1046,31 +990,6 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set override def toString = "Request(line=%s, %s trees)".format(line, trees.size) } - def createBindings: Bindings = new IBindings { - override def put(name: String, value: Object): Object = { - val n = name.indexOf(":") - val p: NamedParam = if (n < 0) (name, value) else { - val nme = name.substring(0, n).trim - val tpe = name.substring(n + 1).trim - NamedParamClass(nme, tpe, value) - } - if (!p.name.startsWith("javax.script")) bind(p) - null - } - } - - @throws[ScriptException] - def compile(script: String): CompiledScript = eval("new javax.script.CompiledScript { def eval(context: javax.script.ScriptContext): Object = { " + script + " }.asInstanceOf[Object]; def getEngine: javax.script.ScriptEngine = engine }").asInstanceOf[CompiledScript] - - @throws[ScriptException] - def compile(reader: java.io.Reader): CompiledScript = compile(stringFromReader(reader)) - - @throws[ScriptException] - def eval(script: String, context: ScriptContext): Object = compiled(script).eval(context) - - @throws[ScriptException] - def eval(reader: java.io.Reader, context: ScriptContext): Object = eval(stringFromReader(reader), context) - override def finalize = close /** Returns the name of the most recent interpreter result. @@ -1267,54 +1186,9 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set /** Utility methods for the Interpreter. */ object IMain { - import java.util.Arrays.{ asList => asJavaList } /** Dummy identifier fragement inserted at the cursor before presentation compilation. Needed to support completion of `global.def` */ val DummyCursorFragment = "_CURSOR_" - class Factory extends ScriptEngineFactory { - @BeanProperty - val engineName = "Scala Interpreter" - - @BeanProperty - val engineVersion = "1.0" - - @BeanProperty - val extensions: JList[String] = asJavaList("scala") - - @BeanProperty - val languageName = "Scala" - - @BeanProperty - val languageVersion = scala.util.Properties.versionString - - def getMethodCallSyntax(obj: String, m: String, args: String*): String = null - - @BeanProperty - val mimeTypes: JList[String] = asJavaList("application/x-scala") - - @BeanProperty - val names: JList[String] = asJavaList("scala") - - def getOutputStatement(toDisplay: String): String = null - - def getParameter(key: String): Object = key match { - case ScriptEngine.ENGINE => engineName - case ScriptEngine.ENGINE_VERSION => engineVersion - case ScriptEngine.LANGUAGE => languageName - case ScriptEngine.LANGUAGE_VERSION => languageVersion - case ScriptEngine.NAME => names.get(0) - case _ => null - } - - def getProgram(statements: String*): String = null - - def getScriptEngine: ScriptEngine = { - val settings = new Settings() - settings.usemanifestcp.value = true - new IMain(this, settings) - } - } - // The two name forms this is catching are the two sides of this assignment: // // $line3.$read.$iw.$iw.Bippy = @@ -1366,5 +1240,10 @@ object IMain { def stripImpl(str: String): String = naming.unmangle(str) } + private[interpreter] def defaultSettings = new Settings() + private[scala] def defaultOut = new NewLinePrintWriter(new ConsoleWriter, true) + + /** construct an interpreter that reports to Console */ + def apply(initialSettings: Settings = defaultSettings, out: JPrintWriter = defaultOut) = new IMain(initialSettings, out) } diff --git a/src/repl/scala/tools/nsc/interpreter/Scripted.scala b/src/repl/scala/tools/nsc/interpreter/Scripted.scala new file mode 100644 index 000000000000..25d359bc0e1a --- /dev/null +++ b/src/repl/scala/tools/nsc/interpreter/Scripted.scala @@ -0,0 +1,343 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2016 LAMP/EPFL + */ +package scala +package tools.nsc +package interpreter + +import scala.language.dynamics + +import scala.beans.BeanProperty +import scala.collection.JavaConverters._ +import scala.reflect.classTag +import scala.reflect.internal.util.Position +import scala.tools.nsc.util.stringFromReader +import javax.script._, ScriptContext.{ ENGINE_SCOPE, GLOBAL_SCOPE } +import java.io.{ Closeable, Reader } + +/* A REPL adaptor for the javax.script API. */ +class Scripted(@BeanProperty val factory: ScriptEngineFactory, settings: Settings, out: JPrintWriter) + extends AbstractScriptEngine with Compilable { + + def createBindings: Bindings = new SimpleBindings + + // dynamic context bound under this name + final val ctx = "$ctx" + + // the underlying interpreter, tweaked to handle dynamic bindings + val intp = new IMain(settings, out) { + import global.{ Name, TermName } + + /* Modify the template to snag definitions from dynamic context. + * So object $iw { x + 42 } becomes object $iw { def x = $ctx.x ; x + 42 } + */ + override protected def importsCode(wanted: Set[Name], wrapper: Request#Wrapper, definesClass: Boolean, generousImports: Boolean) = { + + // cull references that can be satisfied from the current dynamic context + val contextual = wanted & contextNames + + if (contextual.nonEmpty) { + val neededContext = (wanted &~ contextual) + TermName(ctx) + val ComputedImports(header, preamble, trailer, path) = super.importsCode(neededContext, wrapper, definesClass, generousImports) + val adjusted = contextual.map { n => + val valname = n.decodedName + s"""def `$valname` = $ctx.`$valname` + def `${valname}_=`(x: Object) = $ctx.`$valname` = x""" + }.mkString(preamble, "\n", "\n") + ComputedImports(header, adjusted, trailer, path) + } + else super.importsCode(wanted, wrapper, definesClass, generousImports) + } + + // names available in current dynamic context + def contextNames: Set[Name] = { + val ctx = compileContext + val terms = for { + scope <- ctx.getScopes.asScala + binding <- Option(ctx.getBindings(scope)) map (_.asScala) getOrElse Nil + key = binding._1 + } yield (TermName(key): Name) + terms.to[Set] + } + + // save first error for exception; console display only if debugging + override lazy val reporter: ReplReporter = new ReplReporter(this) { + override def display(pos: Position, msg: String, severity: Severity): Unit = + if (isReplDebug) super.display(pos, msg, severity) + override def error(pos: Position, msg: String): Unit = { + if (firstError.isEmpty) firstError = Some((pos, msg)) + super.error(pos, msg) + } + override def reset() = { super.reset() ; firstError = None } + } + } + intp.initializeSynchronous() + + var compileContext: ScriptContext = getContext + + val scriptContextRep = new intp.ReadEvalPrint + + def dynamicContext_=(ctx: ScriptContext): Unit = scriptContextRep.callEither("set", ctx) + + def dynamicContext: ScriptContext = scriptContextRep.callEither("value") match { + case Right(ctx: ScriptContext) => ctx + case Left(e) => throw e + case Right(other) => throw new ScriptException(s"Unexpected value for context: $other") + } + + if (intp.isInitializeComplete) { + // compile the dynamic ScriptContext object holder + scriptContextRep compile s""" + |import javax.script._ + |object ${scriptContextRep.evalName} { + | var value: ScriptContext = _ + | def set(x: Any) = value = x.asInstanceOf[ScriptContext] + |} + """.stripMargin + dynamicContext = getContext + + // Bridge dynamic references and script context + intp compileString s""" + |package scala.tools.nsc.interpreter + |import language.dynamics + |import javax.script._, ScriptContext.ENGINE_SCOPE + |object dynamicBindings extends Dynamic { + | def context: ScriptContext = ${ scriptContextRep.evalPath }.value + | // $ctx.x retrieves the attribute x + | def selectDynamic(field: String): Object = context.getAttribute(field) + | // $ctx.x = v + | def updateDynamic(field: String)(value: Object) = context.setAttribute(field, value, ENGINE_SCOPE) + |} + |""".stripMargin + intp beQuietDuring { + intp interpret s"val $ctx: scala.tools.nsc.interpreter.dynamicBindings.type = scala.tools.nsc.interpreter.dynamicBindings" + intp bind ("$engine" -> (this: ScriptEngine with Compilable)) + } + } + + // Set the context for dynamic resolution and run the body. + // Defines attributes available for evaluation. + // Avoid reflective access if using default context. + def withScriptContext[A](context: ScriptContext)(body: => A): A = + if (context eq getContext) body else { + val saved = dynamicContext + dynamicContext = context + try body + finally dynamicContext = saved + } + // Defines attributes available for compilation. + def withCompileContext[A](context: ScriptContext)(body: => A): A = { + val saved = compileContext + compileContext = context + try body + finally compileContext = saved + } + + // not obvious that ScriptEngine should accumulate code text + private var code = "" + + private var firstError: Option[(Position, String)] = None + + /* All scripts are compiled. The supplied context defines what references + * not in REPL history are allowed, though a different context may be + * supplied for evaluation of a compiled script. + */ + def compile(script: String, context: ScriptContext): CompiledScript = + withCompileContext(context) { + val cat = code + script + intp.compile(cat, synthetic = false) match { + case Right(req) => + code = "" + new WrappedRequest(req) + case Left(IR.Incomplete) => + code = cat + "\n" + new CompiledScript { + def eval(context: ScriptContext): Object = null + def getEngine: ScriptEngine = Scripted.this + } + case Left(_) => + code = "" + throw firstError map { + case (pos, msg) => new ScriptException(msg, script, pos.line, pos.column) + } getOrElse new ScriptException("compile-time error") + } + } + + // documentation + //protected var context: ScriptContext + //def getContext: ScriptContext = context + + /* Compile with the default context. All references must be resolvable. */ + @throws[ScriptException] + def compile(script: String): CompiledScript = compile(script, context) + + @throws[ScriptException] + def compile(reader: Reader): CompiledScript = compile(stringFromReader(reader), context) + + /* Compile and evaluate with the given context. */ + @throws[ScriptException] + def eval(script: String, context: ScriptContext): Object = compile(script, context).eval(context) + + @throws[ScriptException] + def eval(reader: Reader, context: ScriptContext): Object = compile(stringFromReader(reader), context).eval(context) + + private class WrappedRequest(val req: intp.Request) extends CompiledScript { + var first = true + + private def evalEither(r: intp.Request, ctx: ScriptContext) = { + if (ctx.getWriter == null && ctx.getErrorWriter == null && ctx.getReader == null) r.lineRep.evalEither + else { + val closeables = Array.ofDim[Closeable](2) + val w = if (ctx.getWriter == null) Console.out else { + val v = new WriterOutputStream(ctx.getWriter) + closeables(0) = v + v + } + val e = if (ctx.getErrorWriter == null) Console.err else { + val v = new WriterOutputStream(ctx.getErrorWriter) + closeables(1) = v + v + } + val in = if (ctx.getReader == null) Console.in else ctx.getReader + try { + Console.withOut(w) { + Console.withErr(e) { + Console.withIn(in) { + r.lineRep.evalEither + } + } + } + } finally { + closeables foreach (c => if (c != null) c.close()) + } + } + } + + /* First time, cause lazy evaluation of a memoized result. + * Subsequently, instantiate a new object for evaluation. + * Per the API: Checked exception types thrown by underlying scripting implementations + * must be wrapped in instances of ScriptException. + */ + @throws[ScriptException] + override def eval(context: ScriptContext) = withScriptContext(context) { + if (first) { + val result = evalEither(req, context) match { + case Left(e: RuntimeException) => throw e + case Left(e: Exception) => throw new ScriptException(e) + case Left(e) => throw e + case Right(result) => result.asInstanceOf[Object] + } + intp recordRequest req + first = false + result + } else { + val defines = req.defines + if (defines.isEmpty) { + Scripted.this.eval(s"new ${req.lineRep.readPath}") + intp recordRequest duplicate(req) + null + } else { + val instance = s"val $$INSTANCE = new ${req.lineRep.readPath};" + val newline = (defines map (s => s"val ${s.name} = $$INSTANCE${req.accessPath}.${s.name}")).mkString(instance, ";", ";") + val newreq = intp.requestFromLine(newline).right.get + val ok = newreq.compile + + val result = evalEither(newreq, context) match { + case Left(e: RuntimeException) => throw e + case Left(e: Exception) => throw new ScriptException(e) + case Left(e) => throw e + case Right(result) => intp recordRequest newreq ; result.asInstanceOf[Object] + } + result + } + } + } + + def duplicate(req: intp.Request) = new intp.Request(req.line, req.trees) + + def getEngine: ScriptEngine = Scripted.this + } +} + +object Scripted { + import IMain.{ defaultSettings, defaultOut } + import java.util.Arrays.asList + import scala.util.Properties.versionString + + class Factory extends ScriptEngineFactory { + @BeanProperty val engineName = "Scala REPL" + + @BeanProperty val engineVersion = "2.0" + + @BeanProperty val extensions = asList("scala") + + @BeanProperty val languageName = "Scala" + + @BeanProperty val languageVersion = versionString + + @BeanProperty val mimeTypes = asList("application/x-scala") + + @BeanProperty val names = asList("scala") + + def getMethodCallSyntax(obj: String, m: String, args: String*): String = args.mkString(s"$obj.$m(", ", ", ")") + + def getOutputStatement(toDisplay: String): String = s"Console.println($toDisplay)" + + def getParameter(key: String): Object = key match { + case ScriptEngine.ENGINE => engineName + case ScriptEngine.ENGINE_VERSION => engineVersion + case ScriptEngine.LANGUAGE => languageName + case ScriptEngine.LANGUAGE_VERSION => languageVersion + case ScriptEngine.NAME => names.get(0) + case _ => null + } + + def getProgram(statements: String*): String = statements.mkString("object Main extends App {\n\t", "\n\t", "\n}") + + def getScriptEngine: ScriptEngine = { + val settings = new Settings() + settings.usemanifestcp.value = true + Scripted(this, settings) + } + } + + def apply(factory: ScriptEngineFactory = new Factory, settings: Settings = defaultSettings, out: JPrintWriter = defaultOut) = { + settings.Yreplclassbased.value = true + settings.usejavacp.value = true + val s = new Scripted(factory, settings, out) + s.setBindings(s.createBindings, ScriptContext.ENGINE_SCOPE) + s + } +} + +import java.io.Writer +import java.nio.{ ByteBuffer, CharBuffer } +import java.nio.charset.{ Charset, CodingErrorAction } +import CodingErrorAction.{ REPLACE => Replace } + +/* An OutputStream that decodes bytes and flushes to the writer. */ +class WriterOutputStream(writer: Writer) extends OutputStream { + val decoder = Charset.defaultCharset.newDecoder + decoder onMalformedInput Replace + decoder onUnmappableCharacter Replace + + val byteBuffer = ByteBuffer.allocate(64) + val charBuffer = CharBuffer.allocate(64) + + override def write(b: Int): Unit = { + byteBuffer.put(b.toByte) + byteBuffer.flip() + val result = decoder.decode(byteBuffer, charBuffer, /*eoi=*/ false) + if (byteBuffer.remaining == 0) byteBuffer.clear() + if (charBuffer.position > 0) { + charBuffer.flip() + writer write charBuffer.toString + charBuffer.clear() + } + } + override def close(): Unit = { + decoder.decode(byteBuffer, charBuffer, /*eoi=*/ true) + decoder.flush(charBuffer) + } + override def toString = charBuffer.toString +} diff --git a/src/repl/scala/tools/nsc/interpreter/package.scala b/src/repl/scala/tools/nsc/interpreter/package.scala index 97b32bfa8672..55949b81a5a5 100644 --- a/src/repl/scala/tools/nsc/interpreter/package.scala +++ b/src/repl/scala/tools/nsc/interpreter/package.scala @@ -204,7 +204,7 @@ package object interpreter extends ReplConfig with ReplStrings { /* An s-interpolator that uses `stringOf(arg)` instead of `String.valueOf(arg)`. */ private[nsc] implicit class `smart stringifier`(val sc: StringContext) extends AnyVal { - import StringContext._, runtime.ScalaRunTime.stringOf + import StringContext.treatEscapes, scala.runtime.ScalaRunTime.stringOf def ss(args: Any*): String = sc.standardInterpolator(treatEscapes, args map stringOf) } /* Try (body) lastly (more) */ diff --git a/test/files/run/repl-serialization.scala b/test/files/run/repl-serialization.scala index 55b7519631d1..8bc0dd3a8b82 100644 --- a/test/files/run/repl-serialization.scala +++ b/test/files/run/repl-serialization.scala @@ -36,7 +36,7 @@ object Test { |extract(() => new AA(x + getX() + y + z + zz + O.apply + u.x)) """.stripMargin - imain = new IMain(settings) + imain = IMain(settings) println("== evaluating lines") imain.directBind("extract", "(AnyRef => Unit)", extract) code.lines.foreach(imain.interpret) diff --git a/test/files/run/t1500.scala b/test/files/run/t1500.scala index 30c026f70f9f..5a2735fbf1ab 100644 --- a/test/files/run/t1500.scala +++ b/test/files/run/t1500.scala @@ -20,7 +20,7 @@ object Test { val settings = new Settings() settings.classpath.value = System.getProperty("java.class.path") - val tool = new interpreter.IMain(settings) + val tool = interpreter.IMain(settings) val global = tool.global import global._ diff --git a/test/files/run/t7843-jsr223-service.check b/test/files/run/t7843-jsr223-service.check deleted file mode 100644 index a668df3567bb..000000000000 --- a/test/files/run/t7843-jsr223-service.check +++ /dev/null @@ -1,2 +0,0 @@ -n: Object = 10 -12345678910 diff --git a/test/files/run/t7843-jsr223-service.scala b/test/files/run/t7843-jsr223-service.scala deleted file mode 100644 index 31112212eaf4..000000000000 --- a/test/files/run/t7843-jsr223-service.scala +++ /dev/null @@ -1,8 +0,0 @@ -import scala.tools.nsc.interpreter.IMain - -object Test extends App { - val engine = new IMain.Factory getScriptEngine() - engine.asInstanceOf[IMain].settings.usejavacp.value = true - engine put ("n", 10) - engine eval "1 to n.asInstanceOf[Int] foreach print" -} diff --git a/test/files/run/t7933.check b/test/files/run/t7933.check deleted file mode 100644 index 317e9677c3bc..000000000000 --- a/test/files/run/t7933.check +++ /dev/null @@ -1,2 +0,0 @@ -hello -hello diff --git a/test/files/run/t7933.scala b/test/files/run/t7933.scala deleted file mode 100644 index b06dffcd80a9..000000000000 --- a/test/files/run/t7933.scala +++ /dev/null @@ -1,11 +0,0 @@ -import scala.tools.nsc.interpreter.IMain - -object Test extends App { - val engine = new IMain.Factory getScriptEngine() - engine.asInstanceOf[IMain].settings.usejavacp.value = true - val res2 = engine.asInstanceOf[javax.script.Compilable] - res2 compile "8" eval() - val res5 = res2 compile """println("hello") ; 8""" - res5 eval() - res5 eval() -} diff --git a/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala b/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala new file mode 100644 index 000000000000..a8dc8eb3e071 --- /dev/null +++ b/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala @@ -0,0 +1,83 @@ +package scala.tools.nsc +package interpreter + +import org.junit._, Assert._, runner.RunWith, runners.JUnit4 +import scala.tools.testing.AssertUtil.assertThrows + +@RunWith(classOf[JUnit4]) +class ScriptedTest { + import javax.script._ + import scala.tools.nsc.interpreter.Scripted + + def scripted: ScriptEngine with Compilable = Scripted() + // same as by service discovery + //new ScriptEngineManager().getEngineByName("scala").asInstanceOf[ScriptEngine with Compilable] + + @Test def eval() = { + val engine = scripted + engine.put("foo","bar") + assert("bar" == engine.eval("foo")) + val bindings = engine.createBindings() + bindings.put("foo","baz") + assert("baz" == engine.eval("foo", bindings)) + val c = engine.compile("def f = foo.asInstanceOf[String] ; f * 2") + assert("barbar" == c.eval()) + assert("bazbaz" == c.eval(bindings)) + } + @Test def `SI-7933 multiple eval compiled script`() = { + val engine = scripted + val init = """val i = new java.util.concurrent.atomic.AtomicInteger""" + val code = """i.getAndIncrement()""" + engine eval init + val c = engine compile code + assert(0 == c.eval()) + assert(1 == c.eval()) + } + @Test def `SI-8422 captured i/o`() = { + import java.io.StringWriter + val engine = scripted + val ctx = new SimpleScriptContext + val w = new StringWriter + val code = """print("hello, world")""" + + ctx.setWriter(w) + engine.eval(code, ctx) + assertEquals("hello, world", w.toString) + } + @Test def `SI-8422 captured multi i/o`() = { + import java.io.{ StringWriter, StringReader } + import scala.compat.Platform.EOL + val engine = scripted + val ctx = new SimpleScriptContext + val out = new StringWriter + val err = new StringWriter + val text = + """Now is the time + |for all good + |dogs to come for supper.""".stripMargin + val in = new StringReader(text) + + val code = + """var s: String = _ + |var i: Int = 0 + |do { + | s = scala.io.StdIn.readLine() + | val out = if ((i & 1) == 0) Console.out else Console.err + | i += 1 + | Option(s) foreach out.println + |} while (s != null)""".stripMargin + + ctx.setWriter(out) + ctx.setErrorWriter(err) + ctx.setReader(in) + engine.eval(code, ctx) + val lines = text.lines.toList + assertEquals(lines.head + EOL + lines.last + EOL, out.toString) + assertEquals(lines(1) + EOL, err.toString) + } + @Test def `on compile error`(): Unit = { + val engine = scripted + val err = "not found: value foo in def f = foo at line number 11 at column number 16" + assertThrows[ScriptException](engine.compile("def f = foo"), _ == err) + } +} From 80d996b8ade4c0803d1fa7a7f0f733663ca292c3 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Mon, 11 Apr 2016 12:14:09 -0700 Subject: [PATCH 030/153] Include missing web assets in scaladoc --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index bd7616727885..d592b86aff5d 100644 --- a/build.sbt +++ b/build.sbt @@ -507,7 +507,7 @@ lazy val scaladoc = configureAsSubproject(project) name := "scala-compiler-doc", description := "Scala Documentation Generator", libraryDependencies ++= Seq(scalaXmlDep, scalaParserCombinatorsDep, partestDep), - includeFilter in unmanagedResources in Compile := "*.html" | "*.css" | "*.gif" | "*.png" | "*.js" | "*.txt" + includeFilter in unmanagedResources in Compile := "*.html" | "*.css" | "*.gif" | "*.png" | "*.js" | "*.txt" | "*.svg" | "*.eot" | "*.woff" | "*.ttf" ) .dependsOn(compiler) From 6be9fc678b8af5df915905059fd31f0fc1d9d821 Mon Sep 17 00:00:00 2001 From: Olli Helenius Date: Thu, 19 May 2016 23:05:45 +0300 Subject: [PATCH 031/153] SI-9781 Don't convert erroneous expression to assignment `convertToAssignment` is triggered on a type error but it doesn't seem to really care what the error is as long as the expression can be converted to an assignment expression. This patch fixes that by checking whether the qualifier of the selection contains any errors before deciding to continue with the conversion. --- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 4 +++- test/files/neg/t9781.check | 4 ++++ test/files/neg/t9781.scala | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 test/files/neg/t9781.check create mode 100644 test/files/neg/t9781.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 329ce8c23b46..1aed9c3a64cf 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4494,7 +4494,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val opeqStart = if (Statistics.canEnable) Statistics.startTimer(failedOpEqNanos) else null def onError(reportError: => Tree): Tree = fun match { - case Select(qual, name) if !mode.inPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) => + case Select(qual, name) + if !mode.inPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) && !qual.exists(_.isErroneous) => + val qual1 = typedQualifier(qual) if (treeInfo.isVariableOrGetter(qual1)) { if (Statistics.canEnable) Statistics.stopTimer(failedOpEqNanos, opeqStart) diff --git a/test/files/neg/t9781.check b/test/files/neg/t9781.check new file mode 100644 index 000000000000..422c51013a74 --- /dev/null +++ b/test/files/neg/t9781.check @@ -0,0 +1,4 @@ +t9781.scala:3: error: not found: value undefinedSymbol + c(undefinedSymbol) += 1 + ^ +one error found diff --git a/test/files/neg/t9781.scala b/test/files/neg/t9781.scala new file mode 100644 index 000000000000..70234dcca54e --- /dev/null +++ b/test/files/neg/t9781.scala @@ -0,0 +1,4 @@ +object T9781 { + val c: collection.mutable.Map[Int, Int] = ??? + c(undefinedSymbol) += 1 +} From 481a39010f63ccc5811c1d532eb510fd07e265a8 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Fri, 13 May 2016 13:26:13 +0200 Subject: [PATCH 032/153] Improvements to scala.concurrent.Future * Enhanced Scaladocs with groupings and clarifications * traverse now runs the last step like sequence * A few minor non-semantic changes to method implementations --- src/library/scala/concurrent/Future.scala | 159 ++++++++++++++-------- 1 file changed, 101 insertions(+), 58 deletions(-) diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index d9d3d572e8ed..8abd7feeb7ac 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -20,11 +20,14 @@ import scala.collection.generic.CanBuildFrom import scala.reflect.ClassTag -/** The trait that represents futures. +/** A `Future` represents a value which may or may not *currently* be available, + * but will be available at some point, or an exception if that value could not be made available. * - * Asynchronous computations that yield futures are created with the `Future.apply` call: + * Asynchronous computations that yield futures are created with the `Future.apply` call and are computed using a supplied `ExecutionContext`, + * which can be backed by a Thread pool. * * {{{ + * import ExecutionContext.Implicits.global * val s = "Hello" * val f: Future[String] = Future { * s + " future!" @@ -88,6 +91,7 @@ import scala.reflect.ClassTag * thread. That is, the implementation may run multiple callbacks * in a batch within a single `execute()` and it may run * `execute()` either immediately or asynchronously. + * Completion of the Future must *happen-before* the invocation of the callback. */ trait Future[+T] extends Awaitable[T] { import Future.{ InternalCallbackExecutor => internalExecutor } @@ -101,9 +105,13 @@ trait Future[+T] extends Awaitable[T] { * If the future has already been completed with a value, * this will either be applied immediately or be scheduled asynchronously. * + * Note that the returned value of `pf` will be discarded. + * * $swallowsExceptions * $multipleCallbacks * $callbackInContext + * + * @group Callbacks */ @deprecated("use `foreach` or `onComplete` instead (keep in mind that they take total rather than partial functions)", "2.12") def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit = onComplete { @@ -122,9 +130,13 @@ trait Future[+T] extends Awaitable[T] { * * Will not be called in case that the future is completed with a value. * + * Note that the returned value of `pf` will be discarded. + * * $swallowsExceptions * $multipleCallbacks * $callbackInContext + * + * @group Callbacks */ @deprecated("use `onComplete` or `failed.foreach` instead (keep in mind that they take total rather than partial functions)", "2.12") def onFailure[U](@deprecatedName('callback) pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit = onComplete { @@ -139,24 +151,28 @@ trait Future[+T] extends Awaitable[T] { * If the future has already been completed, * this will either be applied immediately or be scheduled asynchronously. * + * Note that the returned value of `f` will be discarded. + * * $swallowsExceptions * $multipleCallbacks * $callbackInContext * * @tparam U only used to accept any return type of the given callback function * @param f the function to be executed when this `Future` completes + * @group Callbacks */ def onComplete[U](@deprecatedName('func) f: Try[T] => U)(implicit executor: ExecutionContext): Unit /* Miscellaneous */ - /** Returns whether the future has already been completed with + /** Returns whether the future had already been completed with * a value or an exception. * * $nonDeterministic * - * @return `true` if the future is already completed, `false` otherwise + * @return `true` if the future was completed, `false` otherwise + * @group Polling */ def isCompleted: Boolean @@ -164,12 +180,13 @@ trait Future[+T] extends Awaitable[T] { * * $nonDeterministic * - * If the future is not completed the returned value will be `None`. - * If the future is completed the value will be `Some(Success(t))` - * if it contains a valid result, or `Some(Failure(error))` if it contains + * If the future was not completed the returned value will be `None`. + * If the future was completed the value will be `Some(Success(t))` + * if it contained a valid result, or `Some(Failure(error))` if it contained * an exception. * * @return `None` if the `Future` wasn't completed, `Some` if it was. + * @group Polling */ def value: Option[Try[T]] @@ -182,6 +199,7 @@ trait Future[+T] extends Awaitable[T] { * If the original `Future` is successful, the returned `Future` is failed with a `NoSuchElementException`. * * @return a failed projection of this `Future`. + * @group Transformations */ def failed: Future[Throwable] = transform({ @@ -201,6 +219,7 @@ trait Future[+T] extends Awaitable[T] { * @tparam U only used to accept any return type of the given callback function * @param f the function which will be executed if this `Future` completes with a result, * the return value of `f` will be discarded. + * @group Callbacks */ def foreach[U](f: T => U)(implicit executor: ExecutionContext): Unit = onComplete { _ foreach f } @@ -209,10 +228,11 @@ trait Future[+T] extends Awaitable[T] { * exception thrown when 's' or 'f' is applied, that exception will be propagated * to the resulting future. * - * @tparam S the type of the returned `Future` - * @param s function that transforms a successful result of the receiver into a successful result of the returned future - * @param f function that transforms a failure of the receiver into a failure of the returned future - * @return a `Future` that will be completed with the transformed value + * @tparam S the type of the returned `Future` + * @param s function that transforms a successful result of the receiver into a successful result of the returned future + * @param f function that transforms a failure of the receiver into a failure of the returned future + * @return a `Future` that will be completed with the transformed value + * @group Transformations */ def transform[S](s: T => S, f: Throwable => Throwable)(implicit executor: ExecutionContext): Future[S] = transform { @@ -224,9 +244,10 @@ trait Future[+T] extends Awaitable[T] { * of this Future. If there is any non-fatal exception thrown when 'f' * is applied then that exception will be propagated to the resulting future. * - * @tparam S the type of the returned `Future` - * @param f function that transforms the result of this future - * @return a `Future` that will be completed with the transformed value + * @tparam S the type of the returned `Future` + * @param f function that transforms the result of this future + * @return a `Future` that will be completed with the transformed value + * @group Transformations */ def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S] @@ -234,9 +255,10 @@ trait Future[+T] extends Awaitable[T] { * of this Future. If there is any non-fatal exception thrown when 'f' * is applied then that exception will be propagated to the resulting future. * - * @tparam S the type of the returned `Future` - * @param f function that transforms the result of this future - * @return a `Future` that will be completed with the transformed value + * @tparam S the type of the returned `Future` + * @param f function that transforms the result of this future + * @return a `Future` that will be completed with the transformed value + * @group Transformations */ def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): Future[S] @@ -257,11 +279,12 @@ trait Future[+T] extends Awaitable[T] { * and `withFilter`. See [[scala.concurrent.Future#flatMap]] for an example of such a comprehension. * * - * @tparam S the type of the returned `Future` - * @param f the function which will be applied to the successful result of this `Future` - * @return a `Future` which will be completed with the result of the application of the function + * @tparam S the type of the returned `Future` + * @param f the function which will be applied to the successful result of this `Future` + * @return a `Future` which will be completed with the result of the application of the function + * @group Transformations */ - def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = transform(_.map(f)) + def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = transform(_ map f) /** Creates a new future by applying a function to the successful result of * this future, and returns the result of the function as the new future. @@ -270,9 +293,10 @@ trait Future[+T] extends Awaitable[T] { * * $forComprehensionExamples * - * @tparam S the type of the returned `Future` - * @param f the function which will be applied to the successful result of this `Future` - * @return a `Future` which will be completed with the result of the application of the function + * @tparam S the type of the returned `Future` + * @param f the function which will be applied to the successful result of this `Future` + * @return a `Future` which will be completed with the result of the application of the function + * @group Transformations */ def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S] = transformWith { case Success(s) => f(s) @@ -282,7 +306,8 @@ trait Future[+T] extends Awaitable[T] { /** Creates a new future with one level of nesting flattened, this method is equivalent * to `flatMap(identity)`. * - * @tparam S the type of the returned `Future` + * @tparam S the type of the returned `Future` + * @group Transformations */ def flatten[S](implicit ev: T <:< Future[S]): Future[S] = flatMap(ev)(internalExecutor) @@ -302,13 +327,15 @@ trait Future[+T] extends Awaitable[T] { * Await.result(h, Duration.Zero) // throw a NoSuchElementException * }}} * - * @param p the predicate to apply to the successful result of this `Future` - * @return a `Future` which will hold the successful result of this `Future` if it matches the predicate or a `NoSuchElementException` + * @param p the predicate to apply to the successful result of this `Future` + * @return a `Future` which will hold the successful result of this `Future` if it matches the predicate or a `NoSuchElementException` + * @group Transformations */ def filter(@deprecatedName('pred) p: T => Boolean)(implicit executor: ExecutionContext): Future[T] = map { r => if (p(r)) r else throw new NoSuchElementException("Future.filter predicate is not satisfied") } /** Used by for-comprehensions. + * @group Transformations */ final def withFilter(p: T => Boolean)(implicit executor: ExecutionContext): Future[T] = filter(p)(executor) @@ -332,9 +359,10 @@ trait Future[+T] extends Awaitable[T] { * Await.result(h, Duration.Zero) // throw a NoSuchElementException * }}} * - * @tparam S the type of the returned `Future` - *  @param pf the `PartialFunction` to apply to the successful result of this `Future` - * @return a `Future` holding the result of application of the `PartialFunction` or a `NoSuchElementException` + * @tparam S the type of the returned `Future` + * @param pf the `PartialFunction` to apply to the successful result of this `Future` + * @return a `Future` holding the result of application of the `PartialFunction` or a `NoSuchElementException` + * @group Transformations */ def collect[S](pf: PartialFunction[T, S])(implicit executor: ExecutionContext): Future[S] = map { @@ -353,9 +381,10 @@ trait Future[+T] extends Awaitable[T] { * Future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3 * }}} * - * @tparam U the type of the returned `Future` - * @param pf the `PartialFunction` to apply if this `Future` fails - * @return a `Future` with the successful value of this `Future` or the result of the `PartialFunction` + * @tparam U the type of the returned `Future` + * @param pf the `PartialFunction` to apply if this `Future` fails + * @return a `Future` with the successful value of this `Future` or the result of the `PartialFunction` + * @group Transformations */ def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] = transform { _ recover pf } @@ -373,9 +402,10 @@ trait Future[+T] extends Awaitable[T] { * Future (6 / 0) recoverWith { case e: ArithmeticException => f } // result: Int.MaxValue * }}} * - * @tparam U the type of the returned `Future` - * @param pf the `PartialFunction` to apply if this `Future` fails - * @return a `Future` with the successful value of this `Future` or the outcome of the `Future` returned by the `PartialFunction` + * @tparam U the type of the returned `Future` + * @param pf the `PartialFunction` to apply if this `Future` fails + * @return a `Future` with the successful value of this `Future` or the outcome of the `Future` returned by the `PartialFunction` + * @group Transformations */ def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U] = transformWith { @@ -391,9 +421,10 @@ trait Future[+T] extends Awaitable[T] { * Otherwise, if `that` future fails, the resulting future is failed * with the throwable stored in `that`. * - * @tparam U the type of the other `Future` - * @param that the other `Future` - * @return a `Future` with the results of both futures or the failure of the first of them that failed + * @tparam U the type of the other `Future` + * @param that the other `Future` + * @return a `Future` with the results of both futures or the failure of the first of them that failed + * @group Transformations */ def zip[U](that: Future[U]): Future[(T, U)] = { implicit val ec = internalExecutor @@ -410,11 +441,12 @@ trait Future[+T] extends Awaitable[T] { * If the application of `f` throws a throwable, the resulting future * is failed with that throwable if it is non-fatal. * - * @tparam U the type of the other `Future` - * @tparam R the type of the resulting `Future` - * @param that the other `Future` - * @param f the function to apply to the results of `this` and `that` - * @return a `Future` with the result of the application of `f` to the results of `this` and `that` + * @tparam U the type of the other `Future` + * @tparam R the type of the resulting `Future` + * @param that the other `Future` + * @param f the function to apply to the results of `this` and `that` + * @return a `Future` with the result of the application of `f` to the results of `this` and `that` + * @group Transformations */ def zipWith[U, R](that: Future[U])(f: (T, U) => R)(implicit executor: ExecutionContext): Future[R] = flatMap(r1 => that.map(r2 => f(r1, r2)))(internalExecutor) @@ -433,9 +465,10 @@ trait Future[+T] extends Awaitable[T] { * h foreach println // Eventually prints 5 * }}} * - * @tparam U the type of the other `Future` and the resulting `Future` - * @param that the `Future` whose result we want to use if this `Future` fails. - * @return a `Future` with the successful result of this or that `Future` or the failure of this `Future` if both fail + * @tparam U the type of the other `Future` and the resulting `Future` + * @param that the `Future` whose result we want to use if this `Future` fails. + * @return a `Future` with the successful result of this or that `Future` or the failure of this `Future` if both fail + * @group Transformations */ def fallbackTo[U >: T](that: Future[U]): Future[U] = if (this eq that) this @@ -447,9 +480,10 @@ trait Future[+T] extends Awaitable[T] { /** Creates a new `Future[S]` which is completed with this `Future`'s result if * that conforms to `S`'s erased type or a `ClassCastException` otherwise. * - * @tparam S the type of the returned `Future` - * @param tag the `ClassTag` which will be used to cast the result of this `Future` - * @return a `Future` holding the casted result of this `Future` or a `ClassCastException` otherwise + * @tparam S the type of the returned `Future` + * @param tag the `ClassTag` which will be used to cast the result of this `Future` + * @return a `Future` holding the casted result of this `Future` or a `ClassCastException` otherwise + * @group Transformations */ def mapTo[S](implicit tag: ClassTag[S]): Future[S] = { implicit val ec = internalExecutor @@ -484,9 +518,12 @@ trait Future[+T] extends Awaitable[T] { * } * }}} * - * @tparam U only used to accept any return type of the given `PartialFunction` - * @param pf a `PartialFunction` which will be conditionally applied to the outcome of this `Future` - * @return a `Future` which will be completed with the exact same outcome as this `Future` but after the `PartialFunction` has been executed. + * $swallowsExceptions + * + * @tparam U only used to accept any return type of the given `PartialFunction` + * @param pf a `PartialFunction` which will be conditionally applied to the outcome of this `Future` + * @return a `Future` which will be completed with the exact same outcome as this `Future` but after the `PartialFunction` has been executed. + * @group Callbacks */ def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): Future[T] = transform { @@ -598,6 +635,13 @@ object Future { /** Starts an asynchronous computation and returns a `Future` instance with the result of that computation. * + * The following expressions are equivalent: + * + * {{{ + * val f1 = Future(expr) + * val f2 = Future.unit.map(_ => expr) + * }}} + * * The result becomes available once the asynchronous computation is completed. * * @tparam T the type of the result @@ -618,7 +662,7 @@ object Future { */ def sequence[A, M[X] <: TraversableOnce[X]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = { in.foldLeft(successful(cbf(in))) { - (fr, fa) => for (r <- fr; a <- fa) yield (r += a) + (fr, fa) => fr.zipWith(fa)(_ += _) }.map(_.result())(InternalCallbackExecutor) } @@ -791,10 +835,9 @@ object Future { * @return the `Future` of the `TraversableOnce` of results */ def traverse[A, B, M[X] <: TraversableOnce[X]](in: M[A])(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], executor: ExecutionContext): Future[M[B]] = - in.foldLeft(successful(cbf(in))) { (fr, a) => - val fb = fn(a) - for (r <- fr; b <- fb) yield (r += b) - }.map(_.result()) + in.foldLeft(successful(cbf(in))) { + (fr, a) => fr.zipWith(fn(a))(_ += _) + }.map(_.result())(InternalCallbackExecutor) // This is used to run callbacks which are internal From 72a59d932db6f16defd14bd729e0f6ec894c7e1b Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 19 May 2016 21:58:55 +0200 Subject: [PATCH 033/153] Rename nsc.backend.jvm.CodeGenTools to testing.BytecodeTesting --- test/junit/scala/issues/BytecodeTest.scala | 2 +- test/junit/scala/issues/OptimizedBytecodeTest.scala | 4 ++-- .../scala/tools/nsc/backend/jvm/BTypesTest.scala | 2 +- .../tools/nsc/backend/jvm/DefaultMethodTest.scala | 2 +- .../tools/nsc/backend/jvm/DirectCompileTest.scala | 2 +- .../scala/tools/nsc/backend/jvm/IndyLambdaTest.scala | 2 +- .../scala/tools/nsc/backend/jvm/IndySammyTest.scala | 2 +- .../tools/nsc/backend/jvm/StringConcatTest.scala | 2 +- .../backend/jvm/analysis/NullnessAnalyzerTest.scala | 2 +- .../backend/jvm/analysis/ProdConsAnalyzerTest.scala | 2 +- .../tools/nsc/backend/jvm/opt/AnalyzerTest.scala | 2 +- .../nsc/backend/jvm/opt/BTypesFromClassfileTest.scala | 2 +- .../tools/nsc/backend/jvm/opt/CallGraphTest.scala | 2 +- .../nsc/backend/jvm/opt/ClosureOptimizerTest.scala | 2 +- .../backend/jvm/opt/CompactLocalVariablesTest.scala | 2 +- .../backend/jvm/opt/EmptyExceptionHandlersTest.scala | 2 +- .../jvm/opt/EmptyLabelsAndLineNumbersTest.scala | 2 +- .../tools/nsc/backend/jvm/opt/InlineInfoTest.scala | 2 +- .../tools/nsc/backend/jvm/opt/InlineWarningTest.scala | 2 +- .../backend/jvm/opt/InlinerIllegalAccessTest.scala | 2 +- .../jvm/opt/InlinerSeparateCompilationTest.scala | 2 +- .../scala/tools/nsc/backend/jvm/opt/InlinerTest.scala | 2 +- .../nsc/backend/jvm/opt/MethodLevelOptsTest.scala | 2 +- .../nsc/backend/jvm/opt/ScalaInlineInfoTest.scala | 2 +- .../tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala | 2 +- .../nsc/backend/jvm/opt/UnreachableCodeTest.scala | 2 +- .../backend/jvm/opt/UnusedLocalVariablesTest.scala | 2 +- .../nsc/transform/delambdafy/DelambdafyTest.scala | 4 +--- .../nsc/transform/patmat/PatmatBytecodeTest.scala | 3 +-- .../BytecodeTesting.scala} | 11 +++++------ 30 files changed, 35 insertions(+), 39 deletions(-) rename test/junit/scala/tools/{nsc/backend/jvm/CodeGenTools.scala => testing/BytecodeTesting.scala} (98%) diff --git a/test/junit/scala/issues/BytecodeTest.scala b/test/junit/scala/issues/BytecodeTest.scala index 7b9474b52e2b..8aa76bbac24f 100644 --- a/test/junit/scala/issues/BytecodeTest.scala +++ b/test/junit/scala/issues/BytecodeTest.scala @@ -6,7 +6,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import scala.tools.nsc.backend.jvm.AsmUtils -import scala.tools.nsc.backend.jvm.CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import org.junit.Assert._ import scala.collection.JavaConverters._ diff --git a/test/junit/scala/issues/OptimizedBytecodeTest.scala b/test/junit/scala/issues/OptimizedBytecodeTest.scala index c69229ae2295..9c0fbebde77e 100644 --- a/test/junit/scala/issues/OptimizedBytecodeTest.scala +++ b/test/junit/scala/issues/OptimizedBytecodeTest.scala @@ -6,9 +6,9 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import org.junit.Assert._ -import scala.tools.nsc.backend.jvm.{AsmUtils, CodeGenTools} +import scala.tools.nsc.backend.jvm.AsmUtils -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala index e7bbbb9a4f23..ebeb57714993 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala @@ -7,7 +7,7 @@ import org.junit.Test import scala.tools.asm.Opcodes import org.junit.Assert._ -import scala.tools.nsc.backend.jvm.CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) diff --git a/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala index 7d4ae866fcaf..0991e5fbcf9a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala @@ -6,7 +6,7 @@ import org.junit.Test import scala.collection.JavaConverters import scala.tools.asm.Opcodes import scala.tools.asm.tree.ClassNode -import scala.tools.nsc.backend.jvm.CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import JavaConverters._ import scala.tools.testing.ClearAfterClass diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala index e984b7551898..ab57c5a1c552 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala @@ -4,7 +4,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.asm.Opcodes._ import scala.tools.partest.ASMConverters._ import scala.tools.testing.ClearAfterClass diff --git a/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala b/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala index b906942ffa1a..66054f246f1a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala @@ -6,7 +6,7 @@ import org.junit.{Assert, Test} import scala.tools.asm.{Handle, Opcodes} import scala.tools.asm.tree.InvokeDynamicInsnNode import scala.tools.nsc.backend.jvm.AsmUtils._ -import scala.tools.nsc.backend.jvm.CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.testing.ClearAfterClass import scala.collection.JavaConverters._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala index 5c2ab6a2c785..598899c7051d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala @@ -9,7 +9,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import scala.tools.asm.tree._ import scala.tools.nsc.reporters.StoreReporter -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala index fc0c96e71a07..f300090268b3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala @@ -9,7 +9,7 @@ import org.junit.Assert._ import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import scala.tools.testing.ClearAfterClass diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala index 075f42d18f11..d37adb226581 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala @@ -8,7 +8,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.asm.tree.{AbstractInsnNode, MethodNode} import scala.tools.nsc.backend.jvm.BTypes._ import scala.tools.partest.ASMConverters diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala index 8d4bc19ec359..7f6aaca67cf2 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala @@ -11,7 +11,7 @@ import scala.tools.asm.Opcodes import scala.tools.asm.tree.AbstractInsnNode import scala.tools.partest.ASMConverters._ import scala.tools.testing.ClearAfterClass -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import AsmUtils._ @RunWith(classOf[JUnit4]) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala index 09675870f0ed..7f07ce51d3d3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala @@ -11,7 +11,7 @@ import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ import scala.tools.nsc.backend.jvm.analysis.{AliasingFrame, AliasingAnalyzer} -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala index aba0aab0386e..30d5db06ddea 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala @@ -11,7 +11,7 @@ import org.junit.Assert._ import scala.tools.nsc.backend.jvm.BTypes.InternalName import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala index 9a27c42cac86..e29d41f0614a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala @@ -15,7 +15,7 @@ import scala.tools.asm.tree.analysis._ import scala.tools.nsc.reporters.StoreReporter import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala index e8530af4e0e9..d1432318829d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala @@ -17,7 +17,7 @@ import scala.tools.nsc.io._ import scala.tools.nsc.reporters.StoreReporter import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala index ac1b759fe260..8ee2b2aa6bdf 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala @@ -8,7 +8,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala index 6d566c722f4f..d9479fde1df3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala @@ -8,7 +8,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import scala.tools.testing.ClearAfterClass diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala index 7283e20745d8..a833192fb17d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala @@ -9,7 +9,7 @@ import scala.tools.asm.Opcodes._ import org.junit.Assert._ import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala index 5cb1aab4a90f..dc3eede556bc 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala @@ -8,7 +8,7 @@ import org.junit.Test import scala.collection.generic.Clearable import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index 6dd0a33289a0..428841e0e0f1 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -17,7 +17,7 @@ import scala.tools.nsc.io._ import scala.tools.nsc.reporters.StoreReporter import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala index ab1aef47cde3..e0b1d758f7f9 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala @@ -11,7 +11,7 @@ import org.junit.Assert._ import scala.tools.asm.tree._ import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala index 075513a2b712..748eff88eafa 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala @@ -8,7 +8,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index b7641b5ec717..52ee118a9461 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -12,7 +12,7 @@ import org.junit.Assert._ import scala.tools.asm.tree._ import scala.tools.nsc.reporters.StoreReporter -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 003b2d48803f..1ceaaf7f69de 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -12,7 +12,7 @@ import scala.tools.asm.tree.ClassNode import scala.tools.nsc.backend.jvm.AsmUtils._ import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import scala.tools.testing.ClearAfterClass diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala index 6cb3fd3bba49..ba6bdcf658b5 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala @@ -8,7 +8,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.asm.tree.ClassNode import scala.tools.nsc.backend.jvm.BTypes.{MethodInlineInfo, InlineInfo} import scala.tools.partest.ASMConverters diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala index 99acb318de65..0133fc9dce2a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala @@ -8,7 +8,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import org.junit.Assert._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala index 46f06d1d3977..ca095b8a5177 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala @@ -10,7 +10,7 @@ import org.junit.Assert._ import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import scala.tools.testing.ClearAfterClass diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala index 77e73e64b99c..7ae946f581b5 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala @@ -9,7 +9,7 @@ import scala.tools.asm.Opcodes._ import org.junit.Assert._ import scala.collection.JavaConverters._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import scala.tools.testing.ClearAfterClass diff --git a/test/junit/scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala b/test/junit/scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala index e4bf038f327b..d30f45817773 100644 --- a/test/junit/scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala +++ b/test/junit/scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala @@ -1,9 +1,7 @@ package scala.tools.nsc.transform.delambdafy import scala.reflect.io.Path.jfile2path -import scala.tools.nsc.backend.jvm.CodeGenTools.getGeneratedClassfiles -import scala.tools.nsc.backend.jvm.CodeGenTools.makeSourceFile -import scala.tools.nsc.backend.jvm.CodeGenTools.newCompilerWithoutVirtualOutdir +import scala.tools.testing.BytecodeTesting._ import scala.tools.nsc.io.AbstractFile import scala.tools.testing.TempDir diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index aa83520efb2b..99975abc50b2 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -8,10 +8,9 @@ import scala.tools.asm.Opcodes._ import org.junit.Assert._ import scala.tools.nsc.backend.jvm.AsmUtils._ -import scala.tools.nsc.backend.jvm.CodeGenTools import scala.tools.testing.AssertUtil._ -import CodeGenTools._ +import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import scala.tools.testing.ClearAfterClass diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/testing/BytecodeTesting.scala similarity index 98% rename from test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala rename to test/junit/scala/tools/testing/BytecodeTesting.scala index 389e5b2ead3b..21b1ce2e77f3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala +++ b/test/junit/scala/tools/testing/BytecodeTesting.scala @@ -1,4 +1,4 @@ -package scala.tools.nsc.backend.jvm +package scala.tools.testing import org.junit.Assert._ @@ -10,14 +10,13 @@ import scala.tools.asm.tree.{AbstractInsnNode, ClassNode, MethodNode} import scala.tools.cmd.CommandLineParser import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.reporters.StoreReporter -import scala.tools.nsc.settings.MutableSettings -import scala.tools.nsc.{Settings, Global} +import scala.tools.nsc.{Global, Settings} import scala.tools.partest.ASMConverters import scala.collection.JavaConverters._ -import scala.tools.testing.TempDir -import AsmUtils._ +import scala.tools.nsc.backend.jvm.AsmUtils -object CodeGenTools { +object BytecodeTesting { + import AsmUtils._ import ASMConverters._ def genMethod( flags: Int = Opcodes.ACC_PUBLIC, From 5d5a6aa154ab533dca4a0e589a7ae67c3c037d61 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 20 May 2016 10:59:21 +0200 Subject: [PATCH 034/153] Better abstraction for bytecode tests. Also organize some imports. --- test/junit/scala/issues/BytecodeTest.scala | 44 +++-- .../scala/issues/OptimizedBytecodeTest.scala | 47 +++-- .../tools/nsc/backend/jvm/BTypesTest.scala | 33 ++-- .../nsc/backend/jvm/DefaultMethodTest.scala | 15 +- .../nsc/backend/jvm/DirectCompileTest.scala | 24 +-- .../nsc/backend/jvm/IndyLambdaTest.scala | 24 ++- .../tools/nsc/backend/jvm/IndySammyTest.scala | 24 +-- .../nsc/backend/jvm/StringConcatTest.scala | 18 +- .../jvm/analysis/NullnessAnalyzerTest.scala | 47 +++-- .../jvm/analysis/ProdConsAnalyzerTest.scala | 27 +-- .../nsc/backend/jvm/opt/AnalyzerTest.scala | 25 +-- .../jvm/opt/BTypesFromClassfileTest.scala | 28 ++- .../nsc/backend/jvm/opt/CallGraphTest.scala | 34 ++-- .../jvm/opt/ClosureOptimizerTest.scala | 37 ++-- .../jvm/opt/CompactLocalVariablesTest.scala | 20 +-- .../jvm/opt/EmptyExceptionHandlersTest.scala | 25 +-- .../opt/EmptyLabelsAndLineNumbersTest.scala | 10 +- .../nsc/backend/jvm/opt/InlineInfoTest.scala | 31 ++-- .../backend/jvm/opt/InlineWarningTest.scala | 42 ++--- .../jvm/opt/InlinerIllegalAccessTest.scala | 29 ++- .../opt/InlinerSeparateCompilationTest.scala | 9 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 44 +++-- .../backend/jvm/opt/MethodLevelOptsTest.scala | 66 ++++--- .../backend/jvm/opt/ScalaInlineInfoTest.scala | 25 ++- .../backend/jvm/opt/SimplifyJumpsTest.scala | 10 +- .../backend/jvm/opt/UnreachableCodeTest.scala | 34 ++-- .../jvm/opt/UnusedLocalVariablesTest.scala | 23 ++- .../transform/delambdafy/DelambdafyTest.scala | 14 +- .../transform/patmat/PatmatBytecodeTest.scala | 30 ++-- .../scala/tools/testing/BytecodeTesting.scala | 169 +++++++++--------- 30 files changed, 453 insertions(+), 555 deletions(-) diff --git a/test/junit/scala/issues/BytecodeTest.scala b/test/junit/scala/issues/BytecodeTest.scala index 8aa76bbac24f..3fd5e3a22229 100644 --- a/test/junit/scala/issues/BytecodeTest.scala +++ b/test/junit/scala/issues/BytecodeTest.scala @@ -1,23 +1,22 @@ package scala.issues +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test - -import scala.tools.asm.Opcodes._ -import scala.tools.nsc.backend.jvm.AsmUtils -import scala.tools.testing.BytecodeTesting._ -import org.junit.Assert._ import scala.collection.JavaConverters._ import scala.tools.asm.Opcodes +import scala.tools.asm.Opcodes._ import scala.tools.asm.tree.ClassNode +import scala.tools.nsc.backend.jvm.AsmUtils import scala.tools.partest.ASMConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class BytecodeTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler()) +class BytecodeTest extends BytecodeTesting { + import compiler._ @Test def t8731(): Unit = { @@ -37,7 +36,7 @@ class BytecodeTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertTrue(getSingleMethod(c, "f").instructions.count(_.isInstanceOf[TableSwitch]) == 1) assertTrue(getSingleMethod(c, "g").instructions.count(_.isInstanceOf[LookupSwitch]) == 1) @@ -64,9 +63,9 @@ class BytecodeTest extends ClearAfterClass { |@AnnotB class B """.stripMargin - val run = new compiler.Run() + val run = new global.Run() run.compileSources(List(new BatchSourceFile("AnnotA.java", annotA), new BatchSourceFile("AnnotB.java", annotB), new BatchSourceFile("Test.scala", scalaSrc))) - val outDir = compiler.settings.outputDirs.getSingleOutput.get + val outDir = global.settings.outputDirs.getSingleOutput.get val outfiles = (for (f <- outDir.iterator if !f.isDirectory) yield (f.name, f.toByteArray)).toList def check(classfile: String, annotName: String) = { @@ -98,7 +97,7 @@ class BytecodeTest extends ClearAfterClass { | } |} """.stripMargin - val List(mirror, module) = compileClasses(compiler)(code) + val List(mirror, module) = compileClasses(code) val unapplyLineNumbers = getSingleMethod(module, "unapply").instructions.filter(_.isInstanceOf[LineNumber]) assert(unapplyLineNumbers == List(LineNumber(2, Label(0))), unapplyLineNumbers) @@ -145,7 +144,7 @@ class BytecodeTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) // t1: no unnecessary GOTOs assertSameCode(getSingleMethod(c, "t1"), List( @@ -271,7 +270,7 @@ class BytecodeTest extends ClearAfterClass { |class C20 extends T8 """.stripMargin - implicit val classes = compileClasses(compiler)(code).map(c => (c.name, c)).toMap + implicit val classes = compileClasses(code).map(c => (c.name, c)).toMap val noForwarder = List('C1, 'C2, 'C3, 'C4, 'C10, 'C11, 'C12, 'C13, 'C16, 'C17) for (c <- noForwarder) assertEquals(findMethods(c, "f"), Nil) @@ -297,7 +296,7 @@ class BytecodeTest extends ClearAfterClass { |trait T2 { def f(x: String) = 1 } |class C extends T1 with T2 """.stripMargin - val List(c, t1, t2) = compileClasses(compiler)(code) + val List(c, t1, t2) = compileClasses(code) assertEquals(findMethods(c, "f"), Nil) } @@ -329,7 +328,7 @@ class BytecodeTest extends ClearAfterClass { | |class K12 extends J2 with T2 """.stripMargin - implicit val classes = compileClasses(compiler)(code, List(j1, j2, j3, j4)).map(c => (c.name, c)).toMap + implicit val classes = compileClasses(code, List(j1, j2, j3, j4)).map(c => (c.name, c)).toMap val noForwarder = List('K1, 'K2, 'K3, 'K4, 'K5, 'K6, 'K7, 'K8, 'K9, 'K10, 'K11) for (c <- noForwarder) assertEquals(findMethods(c, "f"), Nil) @@ -339,7 +338,7 @@ class BytecodeTest extends ClearAfterClass { @Test def invocationReceivers(): Unit = { - val List(c1, c2, t, u) = compileClasses(compiler)(invocationReceiversTestCode.definitions("Object")) + val List(c1, c2, t, u) = compileClasses(invocationReceiversTestCode.definitions("Object")) // mixin forwarder in C1 assertSameCode(getSingleMethod(c1, "clone"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "T", "clone", "()Ljava/lang/Object;", false), Op(ARETURN))) assertInvoke(getSingleMethod(c1, "f1"), "T", "clone") @@ -349,7 +348,7 @@ class BytecodeTest extends ClearAfterClass { assertInvoke(getSingleMethod(c2, "f2"), "T", "clone") assertInvoke(getSingleMethod(c2, "f3"), "C1", "clone") - val List(c1b, c2b, tb, ub) = compileClasses(compiler)(invocationReceiversTestCode.definitions("String")) + val List(c1b, c2b, tb, ub) = compileClasses(invocationReceiversTestCode.definitions("String")) def ms(c: ClassNode, n: String) = c.methods.asScala.toList.filter(_.name == n) assert(ms(tb, "clone").length == 1) assert(ms(ub, "clone").isEmpty) @@ -396,9 +395,8 @@ class BytecodeTest extends ClearAfterClass { | def f3(j: a.J) = j.f |} """.stripMargin - val List(c) = compileClasses(compiler)(cC, javaCode = List((aC, "A.java"), (bC, "B.java"), (iC, "I.java"), (jC, "J.java"))) + val List(c) = compileClasses(cC, javaCode = List((aC, "A.java"), (bC, "B.java"), (iC, "I.java"), (jC, "J.java"))) assertInvoke(getSingleMethod(c, "f1"), "a/B", "f") // receiver needs to be B (A is not accessible in class C, package b) - println(getSingleMethod(c, "f2").instructions.stringLines) assertInvoke(getSingleMethod(c, "f3"), "a/J", "f") // receiver needs to be J } @@ -413,7 +411,7 @@ class BytecodeTest extends ClearAfterClass { | |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertInvoke(getSingleMethod(c, "f1"), "[Ljava/lang/String;", "clone") // array descriptor as receiver assertInvoke(getSingleMethod(c, "f2"), "java/lang/Object", "hashCode") // object receiver assertInvoke(getSingleMethod(c, "f3"), "java/lang/Object", "hashCode") @@ -424,7 +422,7 @@ class BytecodeTest extends ClearAfterClass { def superConstructorArgumentInSpecializedClass(): Unit = { // see comment in SpecializeTypes.forwardCtorCall val code = "case class C[@specialized(Int) T](_1: T)" - val List(c, cMod, cSpec) = compileClasses(compiler)(code) + val List(c, cMod, cSpec) = compileClasses(code) assertSameSummary(getSingleMethod(cSpec, ""), // pass `null` to super constructor, no box-unbox, no Integer created List(ALOAD, ILOAD, PUTFIELD, ALOAD, ACONST_NULL, "", RETURN)) diff --git a/test/junit/scala/issues/OptimizedBytecodeTest.scala b/test/junit/scala/issues/OptimizedBytecodeTest.scala index 9c0fbebde77e..b074215534a5 100644 --- a/test/junit/scala/issues/OptimizedBytecodeTest.scala +++ b/test/junit/scala/issues/OptimizedBytecodeTest.scala @@ -3,22 +3,21 @@ package scala.issues import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.junit.Test + import scala.tools.asm.Opcodes._ import org.junit.Assert._ import scala.tools.nsc.backend.jvm.AsmUtils - import scala.tools.testing.BytecodeTesting._ import scala.tools.partest.ASMConverters import ASMConverters._ import AsmUtils._ - -import scala.tools.testing.ClearAfterClass +import scala.tools.testing.{BytecodeTesting, ClearAfterClass} @RunWith(classOf[JUnit4]) -class OptimizedBytecodeTest extends ClearAfterClass { - val args = "-Yopt:l:classpath -Yopt-warnings" - val compiler = cached("compiler", () => newCompiler(extraArgs = args)) +class OptimizedBytecodeTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:classpath -Yopt-warnings" + import compiler._ @Test def t2171(): Unit = { @@ -28,7 +27,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | def t(): Unit = while (true) m("...") |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertSameCode(getSingleMethod(c, "t"), List(Label(0), Jump(GOTO, Label(0)))) } @@ -46,7 +45,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertSameSummary(getSingleMethod(c, "t"), List( LDC, ASTORE, ALOAD /*0*/, ALOAD /*1*/, "C$$$anonfun$1", IRETURN)) @@ -72,7 +71,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | def h(block: => Unit): Nothing = ??? |} """.stripMargin - val List(c, t, tMod) = compileClasses(compiler)(code, allowMessage = _.msg.contains("not be exhaustive")) + val List(c, t, tMod) = compileClasses(code, allowMessage = _.msg.contains("not be exhaustive")) assertSameSummary(getSingleMethod(c, "t"), List(GETSTATIC, "$qmark$qmark$qmark", ATHROW)) } @@ -97,7 +96,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { |arguments expected by the callee ErrorHandler$::defaultIfIOException(Lscala/Function0;Lscala/Function0;)Ljava/lang/Object;. These values would be discarded |when entering an exception handler declared in the inlined method.""".stripMargin - compileClasses(compiler)(code, allowMessage = _.msg == msg) + compileClasses(code, allowMessage = _.msg == msg) } @Test @@ -110,7 +109,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - compileClasses(compiler)(code) + compileClasses(code) } @Test @@ -120,7 +119,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { |object Warmup { def filter[A](p: Any => Boolean): Any = filter[Any](p) } """.stripMargin val c2 = "class C { def t = warmup.Warmup.filter[Any](x => false) }" - val List(c, _, _) = compileClassesSeparately(List(c1, c2), extraArgs = args) + val List(c, _, _) = compileClassesSeparately(List(c1, c2), extraArgs = compilerArgs) assertInvoke(getSingleMethod(c, "t"), "warmup/Warmup$", "filter") } @@ -135,7 +134,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - compileClasses(compiler)(code) + compileClasses(code) } @Test @@ -163,7 +162,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - compileClasses(compiler)(code) + compileClasses(code) } @Test @@ -179,7 +178,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - compileClasses(compiler)(code) + compileClasses(code) } @Test @@ -201,7 +200,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | val NoContext = self.analyzer.NoContext |} """.stripMargin - compileClasses(compiler)(code) + compileClasses(code) } @Test @@ -218,7 +217,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertSameSummary(getSingleMethod(c, "t"), List( ALOAD /*1*/, INSTANCEOF /*Some*/, IFNE /*A*/, ALOAD /*0*/, "getInt", POP, @@ -237,7 +236,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertSameSummary(getSingleMethod(c, "t"), List( -1 /*A*/, ILOAD /*1*/, TABLESWITCH, -1, ALOAD, "pr", RETURN, @@ -261,7 +260,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { |} """.stripMargin - val cls = compileClassesSeparately(List(c1, c2), extraArgs = args) + val cls = compileClassesSeparately(List(c1, c2), extraArgs = compilerArgs) val c = cls.find(_.name == "C").get assertSameSummary(getSingleMethod(c, "t"), List( GETSTATIC, IFNONNULL, ACONST_NULL, ATHROW, // module load and null checks not yet eliminated @@ -300,7 +299,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | def f2b() = identity(wrapper2(5)) // not inlined |} """.stripMargin - val List(c) = compileClasses(compiler)(code, allowMessage = _.msg.contains("exception handler declared in the inlined method")) + val List(c) = compileClasses(code, allowMessage = _.msg.contains("exception handler declared in the inlined method")) assertInvoke(getSingleMethod(c, "f1a"), "C", "C$$$anonfun$1") assertInvoke(getSingleMethod(c, "f1b"), "C", "wrapper1") assertInvoke(getSingleMethod(c, "f2a"), "C", "C$$$anonfun$3") @@ -318,7 +317,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { | def t = mbarray_apply_minibox(null, 0) |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertNoInvoke(getSingleMethod(c, "t")) } @@ -336,7 +335,7 @@ class OptimizedBytecodeTest extends ClearAfterClass { |object Nill extends Listt |class Listt """.stripMargin - val List(c, nil, nilMod, listt) = compileClasses(compiler)(code) + val List(c, nil, nilMod, listt) = compileClasses(code) assertInvoke(getSingleMethod(c, "t"), "C", "C$$$anonfun$1") } @@ -355,14 +354,14 @@ class OptimizedBytecodeTest extends ClearAfterClass { | final def apply(a: Any): Any = throw new RuntimeException(key) |} """.stripMargin - val List(c, f) = compileClasses(compiler)(code) + val List(c, f) = compileClasses(code) assertInvoke(getSingleMethod(c, "crash"), "C", "map") } @Test def optimiseEnablesNewOpt(): Unit = { val code = """class C { def t = (1 to 10) foreach println }""" - val List(c) = readAsmClasses(compile(newCompiler(extraArgs = "-optimise -deprecation"))(code, allowMessage = _.msg.contains("is deprecated"))) + val List(c) = readAsmClasses(newCompiler(extraArgs = "-optimise -deprecation").compile(code, allowMessage = _.msg.contains("is deprecated"))) assertInvoke(getSingleMethod(c, "t"), "C", "C$$$anonfun$1") // range-foreach inlined from classpath } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala index ebeb57714993..0144fa7366a3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala @@ -1,30 +1,29 @@ package scala.tools.nsc package backend.jvm +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes -import org.junit.Assert._ -import scala.tools.testing.BytecodeTesting._ -import scala.tools.testing.ClearAfterClass +import scala.tools.asm.Opcodes +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class BTypesTest extends ClearAfterClass { - val compiler = cached("compiler", () => { - val comp = newCompiler(extraArgs = "-Yopt:l:none") - new comp.Run() // initializes some of the compiler - comp.exitingDelambdafy(comp.scalaPrimitives.init()) // needed: it's only done when running the backend, and we don't actually run the compiler - comp.exitingDelambdafy(comp.genBCode.bTypes.initializeCoreBTypes()) - comp - }) - import compiler.genBCode.bTypes._ +class BTypesTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + import compiler.global + locally { + new global.Run() // initializes some of the compiler + global.exitingDelambdafy(global.scalaPrimitives.init()) // needed: it's only done when running the backend, and we don't actually run the compiler + global.exitingDelambdafy(global.genBCode.bTypes.initializeCoreBTypes()) + } + import global.genBCode.bTypes._ - def classBTFS(sym: compiler.Symbol) = compiler.exitingDelambdafy(classBTypeFromSymbol(sym)) + def classBTFS(sym: global.Symbol) = global.exitingDelambdafy(classBTypeFromSymbol(sym)) - def jlo = compiler.definitions.ObjectClass - def jls = compiler.definitions.StringClass + def jlo = global.definitions.ObjectClass + def jls = global.definitions.StringClass def o = classBTFS(jlo) def s = classBTFS(jls) def oArr = ArrayBType(o) diff --git a/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala index 0991e5fbcf9a..b538ae0bc603 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala @@ -4,30 +4,29 @@ import org.junit.Assert._ import org.junit.Test import scala.collection.JavaConverters +import scala.collection.JavaConverters._ import scala.tools.asm.Opcodes import scala.tools.asm.tree.ClassNode +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import JavaConverters._ -import scala.tools.testing.ClearAfterClass - -class DefaultMethodTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler()) +class DefaultMethodTest extends BytecodeTesting { + import compiler._ @Test def defaultMethodsViaGenBCode(): Unit = { - import compiler._ + import global._ val code = "package pack { trait T { def foo: Int }}" object makeFooDefaultMethod extends Transformer { val Foo = TermName("foo") /** Transforms a single tree. */ - override def transform(tree: compiler.Tree): compiler.Tree = tree match { + override def transform(tree: global.Tree): global.Tree = tree match { case dd @ DefDef(_, Foo, _, _, _, _) => dd.symbol.setFlag(reflect.internal.Flags.JAVA_DEFAULTMETHOD) copyDefDef(dd)(rhs = Literal(Constant(1)).setType(definitions.IntTpe)) case _ => super.transform(tree) } } - val asmClasses: List[ClassNode] = readAsmClasses(compileTransformed(compiler)(code, Nil, makeFooDefaultMethod.transform(_))) + val asmClasses: List[ClassNode] = readAsmClasses(compiler.compileTransformed(code, Nil, makeFooDefaultMethod.transform(_))) val foo = asmClasses.head.methods.iterator.asScala.toList.last assertTrue("default method should not be abstract", (foo.access & Opcodes.ACC_ABSTRACT) == 0) assertTrue("default method body emitted", foo.instructions.size() > 0) diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala index ab57c5a1c552..65b4264ee9e3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala @@ -1,21 +1,23 @@ package scala.tools.nsc.backend.jvm +import org.junit.Assert._ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Assert._ -import scala.tools.testing.BytecodeTesting._ + import scala.tools.asm.Opcodes._ import scala.tools.partest.ASMConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class DirectCompileTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:method")) +class DirectCompileTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:method" + import compiler._ @Test def testCompile(): Unit = { - val List(("C.class", bytes)) = compile(compiler)( + val List(("C.class", bytes)) = compile( """class C { | def f = 1 |} @@ -26,12 +28,12 @@ class DirectCompileTest extends ClearAfterClass { @Test def testCompileClasses(): Unit = { - val List(cClass, cModuleClass) = compileClasses(compiler)("class C; object C") + val List(cClass, cModuleClass) = compileClasses("class C; object C") assertTrue(cClass.name == "C") assertTrue(cModuleClass.name == "C$") - val List(dMirror, dModuleClass) = compileClasses(compiler)("object D") + val List(dMirror, dModuleClass) = compileClasses("object D") assertTrue(dMirror.name == "D") assertTrue(dModuleClass.name == "D$") @@ -39,7 +41,7 @@ class DirectCompileTest extends ClearAfterClass { @Test def testCompileMethods(): Unit = { - val List(f, g) = compileMethods(compiler)( + val List(f, g) = compileMethods( """def f = 10 |def g = f """.stripMargin) @@ -56,7 +58,7 @@ class DirectCompileTest extends ClearAfterClass { @Test def testDropNonOpAliveLabels(): Unit = { // makes sure that dropNoOp doesn't drop labels that are being used - val List(f) = compileMethods(compiler)("""def f(x: Int) = if (x == 0) "a" else "b"""") + val List(f) = compileMethods("""def f(x: Int) = if (x == 0) "a" else "b"""") assertSameCode(instructionsFromMethod(f).dropLinesFrames, List( Label(0), VarOp(ILOAD, 1), @@ -86,6 +88,6 @@ class DirectCompileTest extends ClearAfterClass { @Test def compileErroneous(): Unit = { - compileClasses(compiler)("class C { def f: String = 1 }", allowMessage = _.msg contains "type mismatch") + compileClasses("class C { def f: String = 1 }", allowMessage = _.msg contains "type mismatch") } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala b/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala index 66054f246f1a..22ced47a02f3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala @@ -1,21 +1,19 @@ package scala.tools.nsc.backend.jvm import org.junit.Assert._ -import org.junit.{Assert, Test} +import org.junit.Test -import scala.tools.asm.{Handle, Opcodes} -import scala.tools.asm.tree.InvokeDynamicInsnNode -import scala.tools.nsc.backend.jvm.AsmUtils._ -import scala.tools.testing.BytecodeTesting._ -import scala.tools.testing.ClearAfterClass import scala.collection.JavaConverters._ +import scala.tools.asm.Handle +import scala.tools.asm.tree.InvokeDynamicInsnNode +import scala.tools.testing.BytecodeTesting -class IndyLambdaTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler()) +class IndyLambdaTest extends BytecodeTesting { + import compiler._ @Test def boxingBridgeMethodUsedSelectively(): Unit = { def implMethodDescriptorFor(code: String): String = { - val method = compileMethods(compiler)(s"""def f = $code """).find(_.name == "f").get + val method = compileMethods(s"""def f = $code """).find(_.name == "f").get val x = method.instructions.iterator.asScala.toList x.flatMap { case insn : InvokeDynamicInsnNode => insn.bsmArgs.collect { case h : Handle => h.getDesc } @@ -48,17 +46,17 @@ class IndyLambdaTest extends ClearAfterClass { assertEquals("(I)I", implMethodDescriptorFor("(x: Int) => x")) // non-builtin sams are like specialized functions - compileClasses(compiler)("class VC(private val i: Int) extends AnyVal; trait FunVC { def apply(a: VC): VC }") + compileClasses("class VC(private val i: Int) extends AnyVal; trait FunVC { def apply(a: VC): VC }") assertEquals("(I)I", implMethodDescriptorFor("((x: VC) => x): FunVC")) - compileClasses(compiler)("trait Fun1[T, U] { def apply(a: T): U }") + compileClasses("trait Fun1[T, U] { def apply(a: T): U }") assertEquals(s"($obj)$str", implMethodDescriptorFor("(x => x.toString): Fun1[Int, String]")) assertEquals(s"($obj)$obj", implMethodDescriptorFor("(x => println(x)): Fun1[Int, Unit]")) assertEquals(s"($obj)$str", implMethodDescriptorFor("((x: VC) => \"\") : Fun1[VC, String]")) assertEquals(s"($str)$obj", implMethodDescriptorFor("((x: String) => new VC(0)) : Fun1[String, VC]")) - compileClasses(compiler)("trait Coll[A, Repr] extends Any") - compileClasses(compiler)("final class ofInt(val repr: Array[Int]) extends AnyVal with Coll[Int, Array[Int]]") + compileClasses("trait Coll[A, Repr] extends Any") + compileClasses("final class ofInt(val repr: Array[Int]) extends AnyVal with Coll[Int, Array[Int]]") assertEquals(s"([I)$obj", implMethodDescriptorFor("((xs: Array[Int]) => new ofInt(xs)): Array[Int] => Coll[Int, Array[Int]]")) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala index 598899c7051d..d7c1f191d0f9 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala @@ -2,26 +2,20 @@ package scala.tools.nsc package backend.jvm import org.junit.Assert.assertEquals +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test import scala.tools.asm.Opcodes._ -import scala.tools.asm.tree._ import scala.tools.nsc.reporters.StoreReporter +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ - -import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class IndySammyTest extends ClearAfterClass { - - val compiler = cached("compiler", () => newCompiler()) - def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = - compileClasses(compiler)(scalaCode, javaCode, allowMessage) +class IndySammyTest extends BytecodeTesting { + import compiler._ def funClassName(from: String, to: String) = s"Fun$from$to" def classPrologue(from: String, to: String) = @@ -45,8 +39,8 @@ class IndySammyTest extends ClearAfterClass { def test(from: String, to: String, arg: String, body: String => String = x => x) (expectedSig: String, lamBody: List[Instruction], appArgs: List[Instruction], ret: Instruction) (allowMessage: StoreReporter#Info => Boolean = _ => false) = { - val cls = compile(s"${classPrologue(from, to)}") - val methodNodes = compileMethods(compiler)(lamDef(from, to, body) +";"+ appDef(arg), allowMessage) + val cls = compileClasses(s"${classPrologue(from, to)}") + val methodNodes = compileMethods(lamDef(from, to, body) +";"+ appDef(arg), allowMessage) val applySig = cls.head.methods.get(0).desc val anonfun = methodNodes.find(_.name contains "$anonfun$").map(convertMethod).get @@ -64,7 +58,7 @@ class IndySammyTest extends ClearAfterClass { } // def testSpecial(lam: String, lamTp: String, arg: String)(allowMessage: StoreReporter#Info => Boolean = _ => false) = { -// val cls = compile("trait Special[@specialized A] { def apply(a: A): A}" ) +// val cls = compileClasses("trait Special[@specialized A] { def apply(a: A): A}" ) // val methodNodes = compileMethods(compiler)(s"def lam : $lamTp = $lam" +";"+ appDef(arg), allowMessage) // // val anonfun = methodNodes.filter(_.name contains "$anonfun$").map(convertMethod) @@ -146,7 +140,7 @@ class IndySammyTest extends ClearAfterClass { // Tests ThisReferringMethodsTraverser @Test def testStaticIfNoThisReference: Unit = { - val methodNodes = compileMethods(compiler)("def foo = () => () => () => 42") + val methodNodes = compileMethods("def foo = () => () => () => 42") methodNodes.forall(m => !m.name.contains("anonfun") || (m.access & ACC_STATIC) == ACC_STATIC) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala index f300090268b3..f231df8af060 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala @@ -1,22 +1,18 @@ package scala.tools.nsc package backend.jvm +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - -import scala.tools.testing.AssertUtil._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class StringConcatTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler()) +class StringConcatTest extends BytecodeTesting { + import compiler._ @Test def appendOverloadNoBoxing(): Unit = { @@ -54,7 +50,7 @@ class StringConcatTest extends ClearAfterClass { | chrs: Array[Char]) = this + str + v + z + c + b + s + i + f + l + d + sbuf + chsq + chrs |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) def invokeNameDesc(m: String): List[String] = getSingleMethod(c, m).instructions collect { case Invoke(_, _, name, desc, _) => name + desc diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala index d37adb226581..358a46102605 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala @@ -2,29 +2,26 @@ package scala.tools.nsc package backend.jvm package analysis +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import scala.tools.testing.BytecodeTesting._ -import scala.tools.asm.tree.{AbstractInsnNode, MethodNode} +import scala.collection.JavaConverters._ +import scala.tools.asm.tree.MethodNode +import scala.tools.nsc.backend.jvm.AsmUtils._ import scala.tools.nsc.backend.jvm.BTypes._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._ -import AsmUtils._ - -import scala.collection.JavaConverters._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) -class NullnessAnalyzerTest extends ClearAfterClass { - val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) - import noOptCompiler.genBCode.bTypes.backendUtils._ +class NullnessAnalyzerTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + import compiler._ + import global.genBCode.bTypes.backendUtils._ - def newNullnessAnalyzer(methodNode: MethodNode, classInternalName: InternalName = "C") = new AsmAnalyzer(methodNode, classInternalName, new NullnessAnalyzer(noOptCompiler.genBCode.bTypes)) + def newNullnessAnalyzer(methodNode: MethodNode, classInternalName: InternalName = "C") = new AsmAnalyzer(methodNode, classInternalName, new NullnessAnalyzer(global.genBCode.bTypes)) def testNullness(analyzer: AsmAnalyzer[NullnessValue], method: MethodNode, query: String, index: Int, nullness: NullnessValue): Unit = { for (i <- findInstr(method, query)) { @@ -53,7 +50,7 @@ class NullnessAnalyzerTest extends ClearAfterClass { @Test def showNullnessFramesTest(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f = this.toString") + val List(m) = compileMethods("def f = this.toString") // NOTE: the frame for an instruction represents the state *before* executing that instr. // So in the frame for `ALOAD 0`, the stack is still empty. @@ -71,14 +68,14 @@ class NullnessAnalyzerTest extends ClearAfterClass { @Test def thisNonNull(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f = this.toString") + val List(m) = compileMethods("def f = this.toString") val a = newNullnessAnalyzer(m) testNullness(a, m, "ALOAD 0", 0, NotNullValue) } @Test def instanceMethodCall(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f(a: String) = a.trim") + val List(m) = compileMethods("def f(a: String) = a.trim") val a = newNullnessAnalyzer(m) testNullness(a, m, "INVOKEVIRTUAL java/lang/String.trim", 1, UnknownValue1) testNullness(a, m, "ARETURN", 1, NotNullValue) @@ -86,7 +83,7 @@ class NullnessAnalyzerTest extends ClearAfterClass { @Test def constructorCall(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f = { val a = new Object; a.toString }") + val List(m) = compileMethods("def f = { val a = new Object; a.toString }") val a = newNullnessAnalyzer(m) // for reference, the output of showAllNullnessFrames(a, m) - note that the frame represents the state *before* executing the instr. @@ -111,7 +108,7 @@ class NullnessAnalyzerTest extends ClearAfterClass { @Test def explicitNull(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f = { var a: Object = null; a }") + val List(m) = compileMethods("def f = { var a: Object = null; a }") val a = newNullnessAnalyzer(m) for ((insn, index, nullness) <- List( ("+ACONST_NULL", 2, NullValue), @@ -122,14 +119,14 @@ class NullnessAnalyzerTest extends ClearAfterClass { @Test def stringLiteralsNotNull(): Unit = { - val List(m) = compileMethods(noOptCompiler)("""def f = { val a = "hi"; a.trim }""") + val List(m) = compileMethods("""def f = { val a = "hi"; a.trim }""") val a = newNullnessAnalyzer(m) testNullness(a, m, "+ASTORE 1", 1, NotNullValue) } @Test def newArraynotNull() { - val List(m) = compileMethods(noOptCompiler)("def f = { val a = new Array[Int](2); a(0) }") + val List(m) = compileMethods("def f = { val a = new Array[Int](2); a(0) }") val a = newNullnessAnalyzer(m) testNullness(a, m, "+NEWARRAY T_INT", 2, NotNullValue) // new array on stack testNullness(a, m, "+ASTORE 1", 1, NotNullValue) // local var (a) @@ -147,7 +144,7 @@ class NullnessAnalyzerTest extends ClearAfterClass { | a.toString |} """.stripMargin - val List(m) = compileMethods(noOptCompiler)(code) + val List(m) = compileMethods(code) val a = newNullnessAnalyzer(m) val toSt = "+INVOKEVIRTUAL java/lang/Object.toString" testNullness(a, m, toSt, 3, UnknownValue1) @@ -173,7 +170,7 @@ class NullnessAnalyzerTest extends ClearAfterClass { | // d is null here, assinged in both branches. |} """.stripMargin - val List(m) = compileMethods(noOptCompiler)(code) + val List(m) = compileMethods(code) val a = newNullnessAnalyzer(m) val trim = "INVOKEVIRTUAL java/lang/String.trim" @@ -209,7 +206,7 @@ class NullnessAnalyzerTest extends ClearAfterClass { | a.asInstanceOf[String].trim // the stack value (LOAD of local a) is still not-null after the CHECKCAST |} """.stripMargin - val List(m) = compileMethods(noOptCompiler)(code) + val List(m) = compileMethods(code) val a = newNullnessAnalyzer(m) val instof = "+INSTANCEOF" diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala index 7f6aaca67cf2..be10370312b5 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala @@ -2,22 +2,23 @@ package scala.tools.nsc package backend.jvm package analysis +import org.junit.Assert._ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Assert._ import scala.tools.asm.Opcodes import scala.tools.asm.tree.AbstractInsnNode +import scala.tools.nsc.backend.jvm.AsmUtils._ import scala.tools.partest.ASMConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import AsmUtils._ @RunWith(classOf[JUnit4]) -class ProdConsAnalyzerTest extends ClearAfterClass { - val noOptCompiler =cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:none")) - import noOptCompiler.genBCode.bTypes.backendUtils._ +class ProdConsAnalyzerTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + import compiler._ + import global.genBCode.bTypes.backendUtils._ def prodToString(producer: AbstractInsnNode) = producer match { case p: InitialProducer => p.toString @@ -48,7 +49,7 @@ class ProdConsAnalyzerTest extends ClearAfterClass { @Test def parameters(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f = this.toString") + val List(m) = compileMethods("def f = this.toString") val a = new ProdConsAnalyzer(m, "C") val call = findInstr(m, "INVOKEVIRTUAL").head @@ -92,7 +93,7 @@ class ProdConsAnalyzerTest extends ClearAfterClass { @Test def branching(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f(x: Int) = { var a = x; if (a == 0) a = 12; a }") + val List(m) = compileMethods("def f(x: Int) = { var a = x; if (a == 0) a = 12; a }") val a = new ProdConsAnalyzer(m, "C") val List(ret) = findInstr(m, "IRETURN") @@ -106,7 +107,7 @@ class ProdConsAnalyzerTest extends ClearAfterClass { @Test def checkCast(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f(o: Object) = o.asInstanceOf[String]") + val List(m) = compileMethods("def f(o: Object) = o.asInstanceOf[String]") val a = new ProdConsAnalyzer(m, "C") assert(findInstr(m, "CHECKCAST java/lang/String").length == 1) @@ -116,7 +117,7 @@ class ProdConsAnalyzerTest extends ClearAfterClass { @Test def instanceOf(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f(o: Object) = o.isInstanceOf[String]") + val List(m) = compileMethods("def f(o: Object) = o.isInstanceOf[String]") val a = new ProdConsAnalyzer(m, "C") assert(findInstr(m, "INSTANCEOF java/lang/String").length == 1) @@ -126,7 +127,7 @@ class ProdConsAnalyzerTest extends ClearAfterClass { @Test def unInitLocal(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f(b: Boolean) = { if (b) { var a = 0; println(a) }; 1 }") + val List(m) = compileMethods("def f(b: Boolean) = { if (b) { var a = 0; println(a) }; 1 }") val a = new ProdConsAnalyzer(m, "C") val List(store) = findInstr(m, "ISTORE") @@ -140,7 +141,7 @@ class ProdConsAnalyzerTest extends ClearAfterClass { @Test def dupCopying(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f = new Object") + val List(m) = compileMethods("def f = new Object") val a = new ProdConsAnalyzer(m, "C") val List(newO) = findInstr(m, "NEW") @@ -222,7 +223,7 @@ class ProdConsAnalyzerTest extends ClearAfterClass { @Test def copyingInsns(): Unit = { - val List(m) = compileMethods(noOptCompiler)("def f = 0l.asInstanceOf[Int]") + val List(m) = compileMethods("def f = 0l.asInstanceOf[Int]") val a = new ProdConsAnalyzer(m, "C") val List(cnst) = findInstr(m, "LCONST_0") diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala index 7f07ce51d3d3..a5fb1e7d17d6 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala @@ -2,28 +2,21 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import org.junit.Assert._ -import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ -import scala.tools.nsc.backend.jvm.analysis.{AliasingFrame, AliasingAnalyzer} - +import scala.tools.nsc.backend.jvm.analysis.{AliasingAnalyzer, AliasingFrame} +import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ -import BackendReporting._ -import BytecodeUtils._ - -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class AnalyzerTest extends ClearAfterClass { - val noOptCompiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:none")) +class AnalyzerTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + import compiler._ @Test def aliasingOfPrimitives(): Unit = { @@ -39,7 +32,7 @@ class AnalyzerTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(noOptCompiler)(code) + val List(c) = compileClasses(code) val a = new AliasingAnalyzer(new BasicInterpreter) val f = findAsmMethod(c, "f") a.analyze("C", f) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala index 30d5db06ddea..1169871ecda0 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala @@ -2,37 +2,29 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.tools.asm.Opcodes._ import scala.tools.nsc.backend.jvm.BTypes.InternalName -import scala.tools.testing.AssertUtil._ - -import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ - -import BackendReporting._ - -import scala.collection.JavaConverters._ +import scala.tools.nsc.backend.jvm.BackendReporting._ +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class BTypesFromClassfileTest { +class BTypesFromClassfileTest extends BytecodeTesting { // inliner enabled -> inlineInfos are collected (and compared) in ClassBTypes - val compiler = newCompiler(extraArgs = "-Yopt:inline-global") + override def compilerArgs = "-Yopt:inline-global" - import compiler._ + import compiler.global._ import definitions._ import genBCode.bTypes import bTypes._ - def duringBackend[T](f: => T) = compiler.exitingDelambdafy(f) + def duringBackend[T](f: => T) = global.exitingDelambdafy(f) - val run = new compiler.Run() // initializes some of the compiler - duringBackend(compiler.scalaPrimitives.init()) // needed: it's only done when running the backend, and we don't actually run the compiler + val run = new global.Run() // initializes some of the compiler + duringBackend(global.scalaPrimitives.init()) // needed: it's only done when running the backend, and we don't actually run the compiler duringBackend(bTypes.initializeCoreBTypes()) def clearCache() = bTypes.classBTypeFromInternalName.clear() diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala index e29d41f0614a..900608837f42 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala @@ -2,46 +2,38 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test + +import scala.collection.JavaConverters._ import scala.collection.generic.Clearable import scala.collection.immutable.IntMap -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - import scala.tools.asm.tree._ -import scala.tools.asm.tree.analysis._ +import scala.tools.nsc.backend.jvm.BackendReporting._ import scala.tools.nsc.reporters.StoreReporter -import scala.tools.testing.AssertUtil._ - +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ -import BackendReporting._ - -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class CallGraphTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:inline-global -Yopt-warnings") - ) - import compiler.genBCode.bTypes +class CallGraphTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:inline-global -Yopt-warnings" + import compiler._ + import global.genBCode.bTypes val notPerRun: List[Clearable] = List( bTypes.classBTypeFromInternalName, bTypes.byteCodeRepository.compilingClasses, bTypes.byteCodeRepository.parsedClasses, bTypes.callGraph.callsites) - notPerRun foreach compiler.perRunCaches.unrecordCache + notPerRun foreach global.perRunCaches.unrecordCache - import compiler.genBCode.bTypes._ + import global.genBCode.bTypes._ import callGraph._ def compile(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { notPerRun.foreach(_.clear()) - compileClasses(compiler)(code, allowMessage = allowMessage).map(c => byteCodeRepository.classNode(c.name).get) + compileClasses(code, allowMessage = allowMessage).map(c => byteCodeRepository.classNode(c.name).get) } def callsInMethod(methodNode: MethodNode): List[MethodInsnNode] = methodNode.instructions.iterator.asScala.collect({ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala index d1432318829d..ddd95ddc0260 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala @@ -2,34 +2,19 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.collection.generic.Clearable -import scala.collection.mutable.ListBuffer -import scala.reflect.internal.util.BatchSourceFile -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - -import scala.tools.asm.tree._ -import scala.tools.asm.tree.analysis._ -import scala.tools.nsc.io._ -import scala.tools.nsc.reporters.StoreReporter -import scala.tools.testing.AssertUtil._ +import scala.tools.asm.Opcodes._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ - -import BackendReporting._ - -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class ClosureOptimizerTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:classpath -Yopt-warnings:_")) +class ClosureOptimizerTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:classpath -Yopt-warnings:_" + import compiler._ @Test def nothingTypedClosureBody(): Unit = { @@ -41,7 +26,7 @@ class ClosureOptimizerTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) val t = findAsmMethod(c, "t") val List(bodyCall) = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Nothing$") assert(bodyCall.getNext.getOpcode == ATHROW) @@ -57,7 +42,7 @@ class ClosureOptimizerTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) val t = findAsmMethod(c, "t") val List(bodyCall) = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Null$") assert(bodyCall.getNext.getOpcode == POP) @@ -74,7 +59,7 @@ class ClosureOptimizerTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertSameCode(getSingleMethod(c, "t"), List(VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "scala/collection/immutable/List", "head", "()Ljava/lang/Object;", false), TypeOp(CHECKCAST, "java/lang/String"), Invoke(INVOKESTATIC, "C", "C$$$anonfun$1", "(Ljava/lang/String;)Ljava/lang/String;", false), @@ -95,7 +80,7 @@ class ClosureOptimizerTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assertSameSummary(getSingleMethod(c, "t"), List(NEW, DUP, LDC, "", ATHROW)) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala index 8ee2b2aa6bdf..50e3af6ee5ef 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala @@ -2,23 +2,21 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.tools.partest.ASMConverters._ import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ +import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class CompactLocalVariablesTest { - +class CompactLocalVariablesTest extends ClearAfterClass { // recurse-unreachable-jumps is required for eliminating catch blocks, in the first dce round they // are still live.only after eliminating the empty handler the catch blocks become unreachable. - val methodOptCompiler = newCompiler(extraArgs = "-Yopt:unreachable-code,compact-locals") - val noCompactVarsCompiler = newCompiler(extraArgs = "-Yopt:unreachable-code") + val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code,compact-locals")) + val noCompactVarsCompiler = cached("noCompactVarsCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) @Test def compactUnused(): Unit = { @@ -58,8 +56,8 @@ class CompactLocalVariablesTest { |} |""".stripMargin - val List(noCompact) = compileMethods(noCompactVarsCompiler)(code) - val List(withCompact) = compileMethods(methodOptCompiler)(code) + val List(noCompact) = noCompactVarsCompiler.compileMethods(code) + val List(withCompact) = methodOptCompiler.compileMethods(code) // code is the same, except for local var indices assertTrue(noCompact.instructions.size == withCompact.instructions.size) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala index d9479fde1df3..9fb4aa1658d4 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala @@ -2,22 +2,23 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.tools.asm.Opcodes._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class EmptyExceptionHandlersTest extends ClearAfterClass { +class EmptyExceptionHandlersTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:unreachable-code" + def dceCompiler = compiler + val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) - val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) val exceptionDescriptor = "java/lang/Exception" @@ -59,8 +60,8 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { def eliminateUnreachableHandler(): Unit = { val code = "def f: Unit = try { } catch { case _: Exception => println(0) }; println(1)" - assertTrue(singleMethod(noOptCompiler)(code).handlers.length == 1) - val optMethod = singleMethod(dceCompiler)(code) + assertTrue(noOptCompiler.singleMethod(code).handlers.length == 1) + val optMethod = dceCompiler.singleMethod(code) assertTrue(optMethod.handlers.isEmpty) val code2 = @@ -72,7 +73,7 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { | println(2) |}""".stripMargin - assertTrue(singleMethod(dceCompiler)(code2).handlers.isEmpty) + assertTrue(dceCompiler.singleMethod(code2).handlers.isEmpty) } @Test @@ -84,6 +85,6 @@ class EmptyExceptionHandlersTest extends ClearAfterClass { | catch { case _: Exception => 2 } |}""".stripMargin - assertTrue(singleMethod(dceCompiler)(code).handlers.length == 1) + assertTrue(dceCompiler.singleMethod(code).handlers.length == 1) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala index a833192fb17d..d57d44f2a3c2 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala @@ -2,16 +2,16 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test + import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.tools.partest.ASMConverters +import scala.tools.partest.ASMConverters._ import scala.tools.testing.AssertUtil._ - import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ @RunWith(classOf[JUnit4]) class EmptyLabelsAndLineNumbersTest { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala index dc3eede556bc..e45d7139a3be 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala @@ -2,36 +2,31 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.collection.generic.Clearable -import org.junit.Assert._ - -import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ -import scala.tools.testing.ClearAfterClass - -import BackendReporting._ import scala.collection.JavaConverters._ +import scala.collection.generic.Clearable +import scala.tools.nsc.backend.jvm.BackendReporting._ +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class InlineInfoTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:classpath")) +class InlineInfoTest extends BytecodeTesting { + import compiler.global + import global.genBCode.bTypes + + override def compilerArgs = "-Yopt:l:classpath" - import compiler.genBCode.bTypes def notPerRun: List[Clearable] = List( bTypes.classBTypeFromInternalName, bTypes.byteCodeRepository.compilingClasses, bTypes.byteCodeRepository.parsedClasses) - notPerRun foreach compiler.perRunCaches.unrecordCache + notPerRun foreach global.perRunCaches.unrecordCache def compile(code: String) = { notPerRun.foreach(_.clear()) - compileClasses(compiler)(code) + compiler.compileClasses(code) } @Test @@ -55,11 +50,11 @@ class InlineInfoTest extends ClearAfterClass { """.stripMargin val classes = compile(code) - val fromSyms = classes.map(c => compiler.genBCode.bTypes.classBTypeFromInternalName(c.name).info.get.inlineInfo) + val fromSyms = classes.map(c => global.genBCode.bTypes.classBTypeFromInternalName(c.name).info.get.inlineInfo) val fromAttrs = classes.map(c => { assert(c.attrs.asScala.exists(_.isInstanceOf[InlineInfoAttribute]), c.attrs) - compiler.genBCode.bTypes.inlineInfoFromClassfile(c) + global.genBCode.bTypes.inlineInfoFromClassfile(c) }) assert(fromSyms == fromAttrs) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index 428841e0e0f1..876c47a84ef1 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -2,41 +2,21 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.collection.generic.Clearable -import scala.collection.mutable.ListBuffer -import scala.reflect.internal.util.BatchSourceFile -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - -import scala.tools.asm.tree._ -import scala.tools.asm.tree.analysis._ -import scala.tools.nsc.io._ -import scala.tools.nsc.reporters.StoreReporter -import scala.tools.testing.AssertUtil._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ -import BackendReporting._ +@RunWith(classOf[JUnit4]) +class InlineWarningTest extends BytecodeTesting { + def optCp = "-Yopt:l:classpath" + override def compilerArgs = s"$optCp -Yopt-warnings" -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass + import compiler._ -@RunWith(classOf[JUnit4]) -class InlineWarningTest extends ClearAfterClass { - val argsNoWarn = "-Yopt:l:classpath" - val args = argsNoWarn + " -Yopt-warnings" - val compiler = cached("compiler", () => newCompiler(extraArgs = args)) - val compilerWarnAll = cached("compilerWarnAll", () => newCompiler(extraArgs = argsNoWarn + " -Yopt-warnings:_")) - - def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false, compiler: Global = compiler): List[ClassNode] = { - compileClasses(compiler)(scalaCode, javaCode, allowMessage) - } + val compilerWarnAll = cached("compilerWarnAll", () => newCompiler(extraArgs = s"$optCp -Yopt-warnings:_")) @Test def nonFinal(): Unit = { @@ -107,10 +87,10 @@ class InlineWarningTest extends ClearAfterClass { assert(c == 1, c) // no warnings here - compileClasses(newCompiler(extraArgs = argsNoWarn + " -Yopt-warnings:none"))(scalaCode, List((javaCode, "A.java"))) + newCompiler(extraArgs = s"$optCp -Yopt-warnings:none").compile(scalaCode, List((javaCode, "A.java"))) c = 0 - compileClasses(newCompiler(extraArgs = argsNoWarn + " -Yopt-warnings:no-inline-mixed"))(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) + newCompiler(extraArgs = s"$optCp -Yopt-warnings:no-inline-mixed").compile(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) assert(c == 2, c) } @@ -164,7 +144,7 @@ class InlineWarningTest extends ClearAfterClass { |that would cause an IllegalAccessError when inlined into class N""".stripMargin var c = 0 - compile(code, compiler = compilerWarnAll, allowMessage = i => { c += 1; i.msg contains warn }) + compilerWarnAll.compile(code, allowMessage = i => { c += 1; i.msg contains warn }) assert(c == 1, c) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala index e0b1d758f7f9..c2ada8afec1f 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala @@ -2,27 +2,22 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - -import scala.tools.asm.tree._ -import scala.tools.testing.AssertUtil._ - -import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.asm.Opcodes._ +import scala.tools.asm.tree._ +import scala.tools.nsc.backend.jvm.AsmUtils._ +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class InlinerIllegalAccessTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:none")) - import compiler.genBCode.bTypes._ +class InlinerIllegalAccessTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + + import compiler._ + import global.genBCode.bTypes._ def addToRepo(cls: List[ClassNode]): Unit = for (c <- cls) byteCodeRepository.add(c, ByteCodeRepository.Classfile) def assertEmpty(ins: Option[AbstractInsnNode]) = for (i <- ins) @@ -44,7 +39,7 @@ class InlinerIllegalAccessTest extends ClearAfterClass { |} """.stripMargin - val allClasses = compileClasses(compiler)(code) + val allClasses = compileClasses(code) val List(cClass, dClass, eClass) = allClasses assert(cClass.name == "a/C" && dClass.name == "a/D" && eClass.name == "b/E", s"${cClass.name}, ${dClass.name}, ${eClass.name}") addToRepo(allClasses) // they are not on the compiler's classpath, so we add them manually to the code repo @@ -120,7 +115,7 @@ class InlinerIllegalAccessTest extends ClearAfterClass { |} """.stripMargin - val allClasses = compileClasses(compiler)(code) + val allClasses = compileClasses(code) val List(cCl, dCl, eCl, fCl, gCl, hCl, iCl) = allClasses addToRepo(allClasses) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala index 748eff88eafa..8a44f12045c1 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala @@ -2,18 +2,11 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ - -import scala.collection.JavaConverters._ object InlinerSeparateCompilationTest { val args = "-Yopt:l:classpath" diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 52ee118a9461..4db7695fddd3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -2,48 +2,44 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test + +import scala.collection.JavaConverters._ import scala.collection.generic.Clearable import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - import scala.tools.asm.tree._ +import scala.tools.nsc.backend.jvm.BackendReporting._ import scala.tools.nsc.reporters.StoreReporter - +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ - -import BackendReporting._ - -import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class InlinerTest extends ClearAfterClass { - val args = "-Yopt:l:classpath -Yopt-warnings" - val compiler = cached("compiler", () => newCompiler(extraArgs = args)) +class InlinerTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:classpath -Yopt-warnings" + val inlineOnlyCompiler = cached("inlineOnlyCompiler", () => newCompiler(extraArgs = "-Yopt:inline-project")) - import compiler.genBCode.bTypes + + import compiler._ + import global.genBCode.bTypes // allows inspecting the caches after a compilation run def notPerRun: List[Clearable] = List( bTypes.classBTypeFromInternalName, bTypes.byteCodeRepository.compilingClasses, bTypes.byteCodeRepository.parsedClasses, bTypes.callGraph.callsites) - notPerRun foreach compiler.perRunCaches.unrecordCache + notPerRun foreach global.perRunCaches.unrecordCache - import compiler.genBCode.bTypes._ - import compiler.genBCode.bTypes.backendUtils._ + import global.genBCode.bTypes.{byteCodeRepository, callGraph, inliner, inlinerHeuristics} import inlinerHeuristics._ def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { notPerRun.foreach(_.clear()) - compileClasses(compiler)(scalaCode, javaCode, allowMessage) + compileClasses(scalaCode, javaCode, allowMessage) // Use the class nodes stored in the byteCodeRepository. The ones returned by compileClasses are not the same, // these are created new from the classfile byte array. They are completely separate instances which cannot // be used to look up methods / callsites in the callGraph hash maps for example. @@ -138,7 +134,7 @@ class InlinerTest extends ClearAfterClass { assertSameCode(convertMethod(g), gBeforeLocalOpt) - compiler.genBCode.bTypes.localOpt.methodOptimizations(g, "C") + global.genBCode.bTypes.localOpt.methodOptimizations(g, "C") assertSameCode(convertMethod(g), invokeQQQ :+ Op(ATHROW)) } @@ -380,7 +376,7 @@ class InlinerTest extends ClearAfterClass { """.stripMargin // use a compiler without local optimizations (cleanups) - val List(c) = compileClasses(inlineOnlyCompiler)(code) + val List(c) = inlineOnlyCompiler.compileClasses(code) val ms @ List(f1, f2, g1, g2) = c.methods.asScala.filter(_.name.length == 2).toList // stack height at callsite of f1 is 1, so max of g1 after inlining is max of f1 + 1 @@ -829,7 +825,7 @@ class InlinerTest extends ClearAfterClass { var c = 0 - compileClasses(newCompiler(extraArgs = args + " -Yopt-warnings:_"))( + newCompiler(extraArgs = compilerArgs + " -Yopt-warnings:_").compileClasses( scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; i.msg contains warn}) @@ -891,7 +887,7 @@ class InlinerTest extends ClearAfterClass { | def t = System.arraycopy(null, 0, null, 0, 0) |} """.stripMargin - val List(c) = compileClasses(newCompiler(extraArgs = args + " -Yopt-inline-heuristics:everything"))(code) + val List(c) = newCompiler(extraArgs = compilerArgs + " -Yopt-inline-heuristics:everything").compileClasses(code) assertInvoke(getSingleMethod(c, "t"), "java/lang/System", "arraycopy") } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 1ceaaf7f69de..3867f101451d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -2,25 +2,23 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.collection.JavaConverters._ +import scala.tools.asm.Opcodes._ import scala.tools.asm.tree.ClassNode import scala.tools.nsc.backend.jvm.AsmUtils._ -import scala.tools.testing.AssertUtil._ - +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass -import scala.collection.JavaConverters._ @RunWith(classOf[JUnit4]) -class MethodLevelOptsTest extends ClearAfterClass { - val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:method")) +class MethodLevelOptsTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:method" + import compiler._ def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1)) @@ -30,14 +28,14 @@ class MethodLevelOptsTest extends ClearAfterClass { def eliminateEmptyTry(): Unit = { val code = "def f = { try {} catch { case _: Throwable => 0; () }; 1 }" val warn = "a pure expression does nothing in statement position" - assertSameCode(singleMethodInstructions(methodOptCompiler)(code, allowMessage = _.msg contains warn), wrapInDefault(Op(ICONST_1), Op(IRETURN))) + assertSameCode(singleMethodInstructions(code, allowMessage = _.msg contains warn), wrapInDefault(Op(ICONST_1), Op(IRETURN))) } @Test def eliminateLoadBoxedUnit(): Unit = { // the compiler inserts a boxed into the try block. it's therefore non-empty (and live) and not eliminated. val code = "def f = { try {} catch { case _: Throwable => 0 }; 1 }" - val m = singleMethod(methodOptCompiler)(code) + val m = singleMethod(code) assertTrue(m.handlers.length == 0) assertSameCode(m, List(Op(ICONST_1), Op(IRETURN))) } @@ -46,7 +44,7 @@ class MethodLevelOptsTest extends ClearAfterClass { def inlineThrowInCatchNotTry(): Unit = { // the try block does not contain the `ATHROW` instruction, but in the catch block, `ATHROW` is inlined val code = "def f(e: Exception) = throw { try e catch { case _: Throwable => e } }" - val m = singleMethod(methodOptCompiler)(code) + val m = singleMethod(code) assertHandlerLabelPostions(m.handlers.head, m.instructions, 0, 3, 5) assertSameCode(m.instructions, wrapInDefault(VarOp(ALOAD, 1), Label(3), Op(ATHROW), Label(5), FrameEntry(4, List(), List("java/lang/Throwable")), Op(POP), VarOp(ALOAD, 1), Op(ATHROW)) @@ -57,7 +55,7 @@ class MethodLevelOptsTest extends ClearAfterClass { def inlineReturnInCatchNotTry(): Unit = { val code = "def f: Int = return { try 1 catch { case _: Throwable => 2 } }" // cannot inline the IRETURN into the try block (because RETURN may throw IllegalMonitorState) - val m = singleMethod(methodOptCompiler)(code) + val m = singleMethod(code) assertHandlerLabelPostions(m.handlers.head, m.instructions, 0, 3, 5) assertSameCode(m.instructions, wrapInDefault(Op(ICONST_1), Label(3), Op(IRETURN), Label(5), FrameEntry(4, List(), List("java/lang/Throwable")), Op(POP), Op(ICONST_2), Op(IRETURN))) @@ -79,7 +77,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | println(x) | } """.stripMargin - val m = singleMethod(methodOptCompiler)(code) + val m = singleMethod(code) assertTrue(m.handlers.isEmpty) assertSameCode(m, List(Op(ICONST_3), Op(IRETURN))) } @@ -99,7 +97,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameCode(getSingleMethod(c, "t"), List( Op(ACONST_NULL), Invoke(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false), Op(ARETURN))) } @@ -116,7 +114,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameCode( getSingleMethod(c, "t"), List(Ldc(LDC, "c"), Op(ARETURN))) } @@ -136,7 +134,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameCode(getSingleMethod(c, "t"), List( Ldc(LDC, "el"), VarOp(ASTORE, 1), @@ -160,7 +158,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameCode(getSingleMethod(c, "t"), List( IntOp(BIPUSH, 23), IntOp(NEWARRAY, 5), Op(POP), VarOp(ILOAD, 1), VarOp(ILOAD, 2), Op(IADD), Op(IRETURN))) } @@ -175,7 +173,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameCode(getSingleMethod(c, "t"), List( TypeOp(NEW, "java/lang/Integer"), Ldc(LDC, "nono"), Invoke(INVOKESPECIAL, "java/lang/Integer", "", "(Ljava/lang/String;)V", false), VarOp(ILOAD, 1), VarOp(ILOAD, 2), Op(IADD), Op(IRETURN))) @@ -201,7 +199,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameCode(getSingleMethod(c, "t"), List(Op(ICONST_0), Op(IRETURN))) } @@ -217,7 +215,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameCode(getSingleMethod(c, "t"), List( IntOp(BIPUSH, 30), VarOp(ISTORE, 3), // no constant propagation, so we keep the store (and load below) of a const VarOp(ILOAD, 1), @@ -238,7 +236,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) val t = getSingleMethod(c, "t") assert(!t.instructions.exists(_.opcode == INVOKEDYNAMIC), t) } @@ -319,7 +317,7 @@ class MethodLevelOptsTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertNoInvoke(getSingleMethod(c, "t1")) assertNoInvoke(getSingleMethod(c, "t2")) @@ -395,7 +393,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameSummary(getSingleMethod(c, "t1"), List(ICONST_0, IRETURN)) assertNoInvoke(getSingleMethod(c, "t2")) assertSameSummary(getSingleMethod(c, "t3"), List(LDC, LDC, LADD, LRETURN)) @@ -459,7 +457,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertNoInvoke(getSingleMethod(c, "t1")) assertSameSummary(getSingleMethod(c, "t2"), List(ICONST_1, ICONST_3, IADD, IRETURN)) assertSameSummary(getSingleMethod(c, "t3"), List(ICONST_3, ICONST_4, IADD, IRETURN)) @@ -524,7 +522,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameSummary(getSingleMethod(c, "t1"), List(NEW, DUP, "", ARETURN)) assertSameCode(getSingleMethod(c, "t2"), List(Op(LCONST_0), Op(LRETURN))) assertSameCode(getSingleMethod(c, "t3"), List(Op(ICONST_1), Op(IRETURN))) @@ -544,7 +542,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameCode( getSingleMethod(c, "t"), List( VarOp(ALOAD, 1), Jump(IFNULL, Label(6)), Op(ICONST_1), Op(IRETURN), Label(6), Op(ICONST_0), Op(IRETURN))) @@ -615,7 +613,7 @@ class MethodLevelOptsTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) def stores(m: String) = getSingleMethod(c, m).instructions.filter(_.opcode == ASTORE) assertEquals(locals(c, "t1"), List(("this",0), ("kept1",1), ("result",2))) @@ -683,7 +681,7 @@ class MethodLevelOptsTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertEquals(locals(c, "t1"), List(("this", 0), ("x", 1))) assertEquals(locals(c, "t2"), List(("this", 0), ("x", 1))) @@ -711,7 +709,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) val t = getSingleMethod(c, "t") assertEquals(t.handlers, Nil) assertEquals(locals(c, "t"), List(("this", 0))) @@ -729,7 +727,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertNoInvoke(getSingleMethod(c, "compare")) } @@ -743,7 +741,7 @@ class MethodLevelOptsTest extends ClearAfterClass { | } |} """.stripMargin - val List(c) = compileClasses(methodOptCompiler)(code) + val List(c) = compileClasses(code) assertSameSummary(getSingleMethod(c, "t"), List( BIPUSH, ILOAD, IF_ICMPNE, diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala index ba6bdcf658b5..5bd285f97f7d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala @@ -2,23 +2,20 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import scala.tools.testing.BytecodeTesting._ -import scala.tools.asm.tree.ClassNode -import scala.tools.nsc.backend.jvm.BTypes.{MethodInlineInfo, InlineInfo} -import scala.tools.partest.ASMConverters -import ASMConverters._ import scala.collection.JavaConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.asm.tree.ClassNode +import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, MethodInlineInfo} +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class ScalaInlineInfoTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler(extraArgs = "-Yopt:l:none")) +class ScalaInlineInfoTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:l:none" + import compiler._ def inlineInfo(c: ClassNode): InlineInfo = c.attrs.asScala.collect({ case a: InlineInfoAttribute => a.inlineInfo }).head @@ -72,7 +69,7 @@ class ScalaInlineInfoTest extends ClearAfterClass { |} """.stripMargin - val cs @ List(c, t, tl, to) = compileClasses(compiler)(code) + val cs @ List(c, t, tl, to) = compileClasses(code) val infoT = inlineInfo(t) val expectT = InlineInfo ( false, // final class @@ -149,7 +146,7 @@ class ScalaInlineInfoTest extends ClearAfterClass { | def nullary: Int |} """.stripMargin - val cs = compileClasses(compiler)(code) + val cs = compileClasses(code) val sams = cs.map(c => (c.name, inlineInfo(c).sam)) assertEquals(sams, List( @@ -165,7 +162,7 @@ class ScalaInlineInfoTest extends ClearAfterClass { @Test def lzyComputeInlineInfo(): Unit = { val code = "class C { object O }" - val List(c, om) = compileClasses(compiler)(code) + val List(c, om) = compileClasses(code) val infoC = inlineInfo(c) val expected = Map( "()V" -> MethodInlineInfo(false,false,false), diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala index 0133fc9dce2a..992a0e541bbc 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala @@ -2,15 +2,15 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import scala.tools.testing.BytecodeTesting._ +import scala.tools.asm.Opcodes._ import scala.tools.partest.ASMConverters -import ASMConverters._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class SimplifyJumpsTest { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala index ca095b8a5177..99a662b8977a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala @@ -2,17 +2,15 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.tools.asm.Opcodes._ +import scala.tools.partest.ASMConverters._ import scala.tools.testing.AssertUtil._ - import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) @@ -20,12 +18,12 @@ class UnreachableCodeTest extends ClearAfterClass { // jvm-1.6 enables emitting stack map frames, which impacts the code generation wrt dead basic blocks, // see comment in BCodeBodyBuilder val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:method")) - val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) - val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) + val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) + val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) def assertEliminateDead(code: (Instruction, Boolean)*): Unit = { val method = genMethod()(code.map(_._1): _*) - dceCompiler.genBCode.bTypes.localOpt.removeUnreachableCodeImpl(method, "C") + dceCompiler.global.genBCode.bTypes.localOpt.removeUnreachableCodeImpl(method, "C") val nonEliminated = instructionsFromMethod(method) val expectedLive = code.filter(_._2).map(_._1).toList assertSameCode(nonEliminated, expectedLive) @@ -112,10 +110,10 @@ class UnreachableCodeTest extends ClearAfterClass { @Test def basicEliminationCompiler(): Unit = { val code = "def f: Int = { return 1; 2 }" - val withDce = singleMethodInstructions(dceCompiler)(code) + val withDce = dceCompiler.singleMethodInstructions(code) assertSameCode(withDce.dropNonOp, List(Op(ICONST_1), Op(IRETURN))) - val noDce = singleMethodInstructions(noOptCompiler)(code) + val noDce = noOptCompiler.singleMethodInstructions(code) // The emitted code is ICONST_1, IRETURN, ICONST_2, IRETURN. The latter two are dead. // @@ -141,23 +139,23 @@ class UnreachableCodeTest extends ClearAfterClass { def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1)) val code = "def f: Int = { return 0; try { 1 } catch { case _: Exception => 2 } }" - val m = singleMethod(dceCompiler)(code) + val m = dceCompiler.singleMethod(code) assertTrue(m.handlers.isEmpty) // redundant (if code is gone, handler is gone), but done once here for extra safety assertSameCode(m.instructions, wrapInDefault(Op(ICONST_0), Op(IRETURN))) val code2 = "def f: Unit = { try { } catch { case _: Exception => () }; () }" // requires fixpoint optimization of methodOptCompiler (dce alone is not enough): first the handler is eliminated, then it's dead catch block. - assertSameCode(singleMethodInstructions(methodOptCompiler)(code2), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.singleMethodInstructions(code2), wrapInDefault(Op(RETURN))) val code3 = "def f: Unit = { try { } catch { case _: Exception => try { } catch { case _: Exception => () } }; () }" - assertSameCode(singleMethodInstructions(methodOptCompiler)(code3), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.singleMethodInstructions(code3), wrapInDefault(Op(RETURN))) // this example requires two iterations to get rid of the outer handler. // the first iteration of DCE cannot remove the inner handler. then the inner (empty) handler is removed. // then the second iteration of DCE removes the inner catch block, and then the outer handler is removed. val code4 = "def f: Unit = { try { try { } catch { case _: Exception => () } } catch { case _: Exception => () }; () }" - assertSameCode(singleMethodInstructions(methodOptCompiler)(code4), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.singleMethodInstructions(code4), wrapInDefault(Op(RETURN))) } @Test // test the dce-testing tools @@ -174,7 +172,7 @@ class UnreachableCodeTest extends ClearAfterClass { } @Test - def bytecodeEquivalence: Unit = { + def bytecodeEquivalence(): Unit = { assertTrue(List(VarOp(ILOAD, 1)) === List(VarOp(ILOAD, 2))) assertTrue(List(VarOp(ILOAD, 1), VarOp(ISTORE, 1)) === @@ -216,7 +214,7 @@ class UnreachableCodeTest extends ClearAfterClass { | def t4 = cons(nt) |} """.stripMargin - val List(c) = compileClasses(noOptCompiler)(code) + val List(c) = noOptCompiler.compileClasses(code) assertSameSummary(getSingleMethod(c, "nl"), List(ACONST_NULL, ARETURN)) @@ -243,7 +241,7 @@ class UnreachableCodeTest extends ClearAfterClass { assertSameSummary(getSingleMethod(c, "t4"), List( ALOAD, ALOAD, "nt", ATHROW, NOP, NOP, NOP, ATHROW)) - val List(cDCE) = compileClasses(dceCompiler)(code) + val List(cDCE) = dceCompiler.compileClasses(code) assertSameSummary(getSingleMethod(cDCE, "t3"), List(ALOAD, NEW, DUP, LDC, "", ATHROW)) assertSameSummary(getSingleMethod(cDCE, "t4"), List(ALOAD, ALOAD, "nt", ATHROW)) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala index 7ae946f581b5..303600aa70fd 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala @@ -2,21 +2,20 @@ package scala.tools.nsc package backend.jvm package opt +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ -import scala.collection.JavaConverters._ -import scala.tools.testing.BytecodeTesting._ +import scala.collection.JavaConverters._ import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) -class UnusedLocalVariablesTest extends ClearAfterClass { - val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) +class UnusedLocalVariablesTest extends BytecodeTesting { + override def compilerArgs = "-Yopt:unreachable-code" + import compiler._ @Test def removeUnusedVar(): Unit = { @@ -49,7 +48,7 @@ class UnusedLocalVariablesTest extends ClearAfterClass { | } |} |""".stripMargin - val cls = compileClasses(dceCompiler)(code).head + val cls = compileClasses(code).head val m = convertMethod(cls.methods.asScala.toList.find(_.desc == "(I)V").get) assertTrue(m.localVars.length == 2) // this, a, but not y @@ -70,7 +69,7 @@ class UnusedLocalVariablesTest extends ClearAfterClass { |} """.stripMargin - val clss2 = compileClasses(dceCompiler)(code2) + val clss2 = compileClasses(code2) val cls2 = clss2.find(_.name == "C").get val companion2 = clss2.find(_.name == "C$").get @@ -82,7 +81,7 @@ class UnusedLocalVariablesTest extends ClearAfterClass { } def assertLocalVarCount(code: String, numVars: Int): Unit = { - assertTrue(singleMethod(dceCompiler)(code).localVars.length == numVars) + assertTrue(singleMethod(code).localVars.length == numVars) } } diff --git a/test/junit/scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala b/test/junit/scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala index d30f45817773..609f481721dd 100644 --- a/test/junit/scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala +++ b/test/junit/scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala @@ -1,15 +1,15 @@ package scala.tools.nsc.transform.delambdafy -import scala.reflect.io.Path.jfile2path -import scala.tools.testing.BytecodeTesting._ -import scala.tools.nsc.io.AbstractFile -import scala.tools.testing.TempDir - import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 +import scala.reflect.io.Path.jfile2path +import scala.tools.nsc.io.AbstractFile +import scala.tools.testing.BytecodeTesting._ +import scala.tools.testing.TempDir + @RunWith(classOf[JUnit4]) class DelambdafyTest { def compileToMultipleOutputWithDelamdbafyMethod(): List[(String, Array[Byte])] = { @@ -53,9 +53,9 @@ object Delambdafy { val extraArgs = "-Ydelambdafy:method" val argsWithOutDir = extraArgs + s" -d $outDirPath -cp $outDirPath" val compiler = newCompilerWithoutVirtualOutdir(extraArgs = argsWithOutDir) - compiler.settings.outputDirs.add(srcFile.file, outDir) + compiler.global.settings.outputDirs.add(srcFile.file, outDir) - new compiler.Run().compileSources(List(srcFile)) + new compiler.global.Run().compileSources(List(srcFile)) val classfiles = getGeneratedClassfiles(outDir) outDir.delete() diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index 99975abc50b2..cc6d1d748356 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -1,25 +1,21 @@ package scala.tools.nsc package transform.patmat +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes._ -import org.junit.Assert._ +import scala.tools.asm.Opcodes._ import scala.tools.nsc.backend.jvm.AsmUtils._ -import scala.tools.testing.AssertUtil._ - +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import scala.tools.testing.ClearAfterClass @RunWith(classOf[JUnit4]) -class PatmatBytecodeTest extends ClearAfterClass { - val compiler = cached("compiler", () => newCompiler()) +class PatmatBytecodeTest extends BytecodeTesting { val optCompiler = cached("optCompiler", () => newCompiler(extraArgs = "-Yopt:l:project")) + import compiler._ + @Test def t6956(): Unit = { val code = @@ -42,7 +38,7 @@ class PatmatBytecodeTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assert(getSingleMethod(c, "s1").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) assert(getSingleMethod(c, "s2").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) } @@ -70,7 +66,7 @@ class PatmatBytecodeTest extends ClearAfterClass { |} """.stripMargin - val List(c) = compileClasses(compiler)(code) + val List(c) = compileClasses(code) assert(getSingleMethod(c, "s1").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) assert(getSingleMethod(c, "s2").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) } @@ -85,7 +81,7 @@ class PatmatBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - val c = compileClasses(optCompiler)(code).head + val c = optCompiler.compileClasses(code).head assertSameSummary(getSingleMethod(c, "a"), List( NEW, DUP, ICONST_1, LDC, "", @@ -102,7 +98,7 @@ class PatmatBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - val c = compileClasses(optCompiler)(code).head + val c = optCompiler.compileClasses(code).head assert(!getSingleMethod(c, "a").instructions.exists(i => i.opcode == IFNULL || i.opcode == IFNONNULL), textify(findAsmMethod(c, "a"))) } @@ -116,7 +112,7 @@ class PatmatBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - val c = compileClasses(optCompiler)(code).head + val c = optCompiler.compileClasses(code).head assertSameSummary(getSingleMethod(c, "a"), List( NEW, DUP, ICONST_1, "boxToInteger", LDC, "", ASTORE /*1*/, ALOAD /*1*/, "y", ASTORE /*2*/, @@ -137,7 +133,7 @@ class PatmatBytecodeTest extends ClearAfterClass { | } |} """.stripMargin - val c = compileClasses(optCompiler)(code, allowMessage = _.msg.contains("may not be exhaustive")).head + val c = optCompiler.compileClasses(code, allowMessage = _.msg.contains("may not be exhaustive")).head val expected = List( ALOAD /*1*/ , INSTANCEOF /*::*/ , IFEQ /*A*/ , @@ -169,7 +165,7 @@ class PatmatBytecodeTest extends ClearAfterClass { | def t9 = { val C(a, _) = C("hi", 23); a.toString } |} """.stripMargin - val List(c, cMod) = compileClasses(optCompiler)(code) + val List(c, cMod) = optCompiler.compileClasses(code) assertSameSummary(getSingleMethod(c, "t1"), List(ICONST_1, ICONST_2, IADD, IRETURN)) assertSameSummary(getSingleMethod(c, "t2"), List(ICONST_1, IRETURN)) assertInvokedMethods(getSingleMethod(c, "t3"), List("C.tplCall", "scala/Tuple2._1", "scala/Tuple2._2$mcI$sp", "scala/MatchError.", "java/lang/String.length")) diff --git a/test/junit/scala/tools/testing/BytecodeTesting.scala b/test/junit/scala/tools/testing/BytecodeTesting.scala index 21b1ce2e77f3..d6f8dbc21937 100644 --- a/test/junit/scala/tools/testing/BytecodeTesting.scala +++ b/test/junit/scala/tools/testing/BytecodeTesting.scala @@ -2,30 +2,99 @@ package scala.tools.testing import org.junit.Assert._ +import scala.collection.JavaConverters._ import scala.collection.mutable.ListBuffer import scala.reflect.internal.util.BatchSourceFile import scala.reflect.io.VirtualDirectory import scala.tools.asm.Opcodes import scala.tools.asm.tree.{AbstractInsnNode, ClassNode, MethodNode} import scala.tools.cmd.CommandLineParser +import scala.tools.nsc.backend.jvm.AsmUtils +import scala.tools.nsc.backend.jvm.AsmUtils._ import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.reporters.StoreReporter import scala.tools.nsc.{Global, Settings} -import scala.tools.partest.ASMConverters -import scala.collection.JavaConverters._ -import scala.tools.nsc.backend.jvm.AsmUtils +import scala.tools.partest.ASMConverters._ + +trait BytecodeTesting extends ClearAfterClass { + def compilerArgs = "" // to be overridden + val compiler = cached("compiler", () => BytecodeTesting.newCompiler(extraArgs = compilerArgs)) +} + +class Compiler(val global: Global) { + import BytecodeTesting._ + + def resetOutput(): Unit = { + global.settings.outputDirs.setSingleOutput(new VirtualDirectory("(memory)", None)) + } + + private def newRun: global.Run = { + global.reporter.reset() + resetOutput() + new global.Run() + } + + private def reporter = global.reporter.asInstanceOf[StoreReporter] + + def checkReport(allowMessage: StoreReporter#Info => Boolean = _ => false): Unit = { + val disallowed = reporter.infos.toList.filter(!allowMessage(_)) // toList prevents an infer-non-wildcard-existential warning. + if (disallowed.nonEmpty) { + val msg = disallowed.mkString("\n") + assert(false, "The compiler issued non-allowed warnings or errors:\n" + msg) + } + } + + def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[(String, Array[Byte])] = { + val run = newRun + run.compileSources(makeSourceFile(scalaCode, "unitTestSource.scala") :: javaCode.map(p => makeSourceFile(p._1, p._2))) + checkReport(allowMessage) + getGeneratedClassfiles(global.settings.outputDirs.getSingleOutput.get) + } + + def compileTransformed(scalaCode: String, javaCode: List[(String, String)] = Nil, beforeBackend: global.Tree => global.Tree): List[(String, Array[Byte])] = { + import global._ + settings.stopBefore.value = "jvm" :: Nil + val run = newRun + val scalaUnit = newCompilationUnit(scalaCode, "unitTestSource.scala") + val javaUnits = javaCode.map(p => newCompilationUnit(p._1, p._2)) + val units = scalaUnit :: javaUnits + run.compileUnits(units, run.parserPhase) + settings.stopBefore.value = Nil + scalaUnit.body = beforeBackend(scalaUnit.body) + checkReport(_ => false) + val run1 = newRun + run1.compileUnits(units, run1.phaseNamed("jvm")) + checkReport(_ => false) + getGeneratedClassfiles(settings.outputDirs.getSingleOutput.get) + } + + def compileClasses(code: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { + readAsmClasses(compile(code, javaCode, allowMessage)) + } + + def compileMethods(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[MethodNode] = { + compileClasses(s"class C { $code }", allowMessage = allowMessage).head.methods.asScala.toList.filterNot(_.name == "") + } + + def singleMethodInstructions(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[Instruction] = { + val List(m) = compileMethods(code, allowMessage = allowMessage) + instructionsFromMethod(m) + } + + def singleMethod(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): Method = { + val List(m) = compileMethods(code, allowMessage = allowMessage) + convertMethod(m) + } +} object BytecodeTesting { - import AsmUtils._ - import ASMConverters._ - - def genMethod( flags: Int = Opcodes.ACC_PUBLIC, - name: String = "m", - descriptor: String = "()V", - genericSignature: String = null, - throwsExceptions: Array[String] = null, - handlers: List[ExceptionHandler] = Nil, - localVars: List[LocalVariable] = Nil)(body: Instruction*): MethodNode = { + def genMethod(flags: Int = Opcodes.ACC_PUBLIC, + name: String = "m", + descriptor: String = "()V", + genericSignature: String = null, + throwsExceptions: Array[String] = null, + handlers: List[ExceptionHandler] = Nil, + localVars: List[LocalVariable] = Nil)(body: Instruction*): MethodNode = { val node = new MethodNode(flags, name, descriptor, genericSignature, throwsExceptions) applyToMethod(node, Method(body.toList, handlers, localVars)) node @@ -38,33 +107,21 @@ object BytecodeTesting { cls } - private def resetOutput(compiler: Global): Unit = { - compiler.settings.outputDirs.setSingleOutput(new VirtualDirectory("(memory)", None)) - } - - def newCompiler(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Global = { + def newCompiler(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Compiler = { val compiler = newCompilerWithoutVirtualOutdir(defaultArgs, extraArgs) - resetOutput(compiler) + compiler.resetOutput() compiler } - def newCompilerWithoutVirtualOutdir(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Global = { + def newCompilerWithoutVirtualOutdir(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Compiler = { def showError(s: String) = throw new Exception(s) val settings = new Settings(showError) val args = (CommandLineParser tokenize defaultArgs) ++ (CommandLineParser tokenize extraArgs) val (_, nonSettingsArgs) = settings.processArguments(args, processAll = true) if (nonSettingsArgs.nonEmpty) showError("invalid compiler flags: " + nonSettingsArgs.mkString(" ")) - new Global(settings, new StoreReporter) - } - - def newRun(compiler: Global): compiler.Run = { - compiler.reporter.reset() - resetOutput(compiler) - new compiler.Run() + new Compiler(new Global(settings, new StoreReporter)) } - def reporter(compiler: Global) = compiler.reporter.asInstanceOf[StoreReporter] - def makeSourceFile(code: String, filename: String): BatchSourceFile = new BatchSourceFile(filename, code) def getGeneratedClassfiles(outDir: AbstractFile): List[(String, Array[Byte])] = { @@ -79,38 +136,6 @@ object BytecodeTesting { files(outDir) } - def checkReport(compiler: Global, allowMessage: StoreReporter#Info => Boolean = _ => false): Unit = { - val disallowed = reporter(compiler).infos.toList.filter(!allowMessage(_)) // toList prevents an infer-non-wildcard-existential warning. - if (disallowed.nonEmpty) { - val msg = disallowed.mkString("\n") - assert(false, "The compiler issued non-allowed warnings or errors:\n" + msg) - } - } - - def compile(compiler: Global)(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[(String, Array[Byte])] = { - val run = newRun(compiler) - run.compileSources(makeSourceFile(scalaCode, "unitTestSource.scala") :: javaCode.map(p => makeSourceFile(p._1, p._2))) - checkReport(compiler, allowMessage) - getGeneratedClassfiles(compiler.settings.outputDirs.getSingleOutput.get) - } - - def compileTransformed(compiler: Global)(scalaCode: String, javaCode: List[(String, String)] = Nil, beforeBackend: compiler.Tree => compiler.Tree): List[(String, Array[Byte])] = { - compiler.settings.stopBefore.value = "jvm" :: Nil - val run = newRun(compiler) - import compiler._ - val scalaUnit = newCompilationUnit(scalaCode, "unitTestSource.scala") - val javaUnits = javaCode.map(p => newCompilationUnit(p._1, p._2)) - val units = scalaUnit :: javaUnits - run.compileUnits(units, run.parserPhase) - compiler.settings.stopBefore.value = Nil - scalaUnit.body = beforeBackend(scalaUnit.body) - checkReport(compiler, _ => false) - val run1 = newRun(compiler) - run1.compileUnits(units, run1.phaseNamed("jvm")) - checkReport(compiler, _ => false) - getGeneratedClassfiles(compiler.settings.outputDirs.getSingleOutput.get) - } - /** * Compile multiple Scala files separately into a single output directory. * @@ -127,8 +152,8 @@ object BytecodeTesting { for (code <- codes) { val compiler = newCompilerWithoutVirtualOutdir(extraArgs = argsWithOutDir) - new compiler.Run().compileSources(List(makeSourceFile(code, "unitTestSource.scala"))) - checkReport(compiler, allowMessage) + new compiler.global.Run().compileSources(List(makeSourceFile(code, "unitTestSource.scala"))) + compiler.checkReport(allowMessage) afterEach(outDir) } @@ -145,24 +170,6 @@ object BytecodeTesting { classfiles.map(p => AsmUtils.readClass(p._2)).sortBy(_.name) } - def compileClasses(compiler: Global)(code: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { - readAsmClasses(compile(compiler)(code, javaCode, allowMessage)) - } - - def compileMethods(compiler: Global)(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[MethodNode] = { - compileClasses(compiler)(s"class C { $code }", allowMessage = allowMessage).head.methods.asScala.toList.filterNot(_.name == "") - } - - def singleMethodInstructions(compiler: Global)(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[Instruction] = { - val List(m) = compileMethods(compiler)(code, allowMessage = allowMessage) - instructionsFromMethod(m) - } - - def singleMethod(compiler: Global)(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): Method = { - val List(m) = compileMethods(compiler)(code, allowMessage = allowMessage) - convertMethod(m) - } - def assertSameCode(method: Method, expected: List[Instruction]): Unit = assertSameCode(method.instructions.dropNonOp, expected) def assertSameCode(actual: List[Instruction], expected: List[Instruction]): Unit = { assert(actual === expected, s"\nExpected: $expected\nActual : $actual") From d9ce4dc1eeb351a52e98c6c0fa1551a5cc3b87f5 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 20 May 2016 08:20:41 +0200 Subject: [PATCH 035/153] Better abstraction for JUnit run tests --- test/junit/scala/issues/RunTest.scala | 16 +++++----------- test/junit/scala/tools/testing/RunTesting.scala | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 test/junit/scala/tools/testing/RunTesting.scala diff --git a/test/junit/scala/issues/RunTest.scala b/test/junit/scala/issues/RunTest.scala index 3ebdc8a72ff6..0686d73d9bdf 100644 --- a/test/junit/scala/issues/RunTest.scala +++ b/test/junit/scala/issues/RunTest.scala @@ -1,13 +1,11 @@ package scala.issues +import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.{AfterClass, BeforeClass, Test} -import org.junit.Assert._ -import scala.reflect.runtime._ -import scala.tools.reflect.ToolBox -import scala.tools.testing.ClearAfterClass +import scala.tools.testing.RunTesting object RunTest { class VC(val x: Any) extends AnyVal @@ -15,12 +13,8 @@ object RunTest { } @RunWith(classOf[JUnit4]) -class RunTest extends ClearAfterClass { - val toolBox = cached("toolbox", () => universe.runtimeMirror(getClass.getClassLoader).mkToolBox()) - - def run[T](code: String): T = { - toolBox.eval(toolBox.parse(code)).asInstanceOf[T] - } +class RunTest extends RunTesting { + import runner._ @Test def classOfValueClassAlias(): Unit = { diff --git a/test/junit/scala/tools/testing/RunTesting.scala b/test/junit/scala/tools/testing/RunTesting.scala new file mode 100644 index 000000000000..1320db42302e --- /dev/null +++ b/test/junit/scala/tools/testing/RunTesting.scala @@ -0,0 +1,17 @@ +package scala.tools.testing + +import scala.reflect.runtime._ +import scala.tools.reflect.ToolBox + +trait RunTesting extends ClearAfterClass { + def compilerArgs = "" // to be overridden + val runner = cached("toolbox", () => Runner.make(compilerArgs)) +} + +class Runner(val toolBox: ToolBox[universe.type]) { + def run[T](code: String): T = toolBox.eval(toolBox.parse(code)).asInstanceOf[T] +} + +object Runner { + def make(compilerArgs: String) = new Runner(universe.runtimeMirror(getClass.getClassLoader).mkToolBox(options = compilerArgs)) +} From ba510abcdcf176c06ba93c8e9dc6398015877f5e Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 20 May 2016 12:22:06 +0200 Subject: [PATCH 036/153] Clean up bytecode testing methods. --- test/junit/scala/issues/BytecodeTest.scala | 84 +++--- .../scala/issues/OptimizedBytecodeTest.scala | 58 ++-- .../nsc/backend/jvm/DefaultMethodTest.scala | 2 +- .../nsc/backend/jvm/DirectCompileTest.scala | 16 +- .../nsc/backend/jvm/IndyLambdaTest.scala | 10 +- .../tools/nsc/backend/jvm/IndySammyTest.scala | 14 +- .../nsc/backend/jvm/StringConcatTest.scala | 4 +- .../jvm/analysis/NullnessAnalyzerTest.scala | 22 +- .../jvm/analysis/ProdConsAnalyzerTest.scala | 68 ++--- .../nsc/backend/jvm/opt/AnalyzerTest.scala | 8 +- .../nsc/backend/jvm/opt/CallGraphTest.scala | 10 +- .../jvm/opt/ClosureOptimizerTest.scala | 20 +- .../jvm/opt/CompactLocalVariablesTest.scala | 4 +- .../jvm/opt/EmptyExceptionHandlersTest.scala | 8 +- .../backend/jvm/opt/InlineWarningTest.scala | 18 +- .../opt/InlinerSeparateCompilationTest.scala | 14 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 260 +++++++++--------- .../backend/jvm/opt/MethodLevelOptsTest.scala | 156 +++++------ .../backend/jvm/opt/UnreachableCodeTest.scala | 32 +-- .../jvm/opt/UnusedLocalVariablesTest.scala | 17 +- .../transform/patmat/PatmatBytecodeTest.scala | 48 ++-- .../scala/tools/testing/BytecodeTesting.scala | 85 ++++-- 22 files changed, 496 insertions(+), 462 deletions(-) diff --git a/test/junit/scala/issues/BytecodeTest.scala b/test/junit/scala/issues/BytecodeTest.scala index 3fd5e3a22229..0bb87a4ea6a2 100644 --- a/test/junit/scala/issues/BytecodeTest.scala +++ b/test/junit/scala/issues/BytecodeTest.scala @@ -36,10 +36,10 @@ class BytecodeTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) - assertTrue(getSingleMethod(c, "f").instructions.count(_.isInstanceOf[TableSwitch]) == 1) - assertTrue(getSingleMethod(c, "g").instructions.count(_.isInstanceOf[LookupSwitch]) == 1) + assertTrue(getInstructions(c, "f").count(_.isInstanceOf[TableSwitch]) == 1) + assertTrue(getInstructions(c, "g").count(_.isInstanceOf[LookupSwitch]) == 1) } @Test @@ -99,7 +99,7 @@ class BytecodeTest extends BytecodeTesting { """.stripMargin val List(mirror, module) = compileClasses(code) - val unapplyLineNumbers = getSingleMethod(module, "unapply").instructions.filter(_.isInstanceOf[LineNumber]) + val unapplyLineNumbers = getInstructions(module, "unapply").filter(_.isInstanceOf[LineNumber]) assert(unapplyLineNumbers == List(LineNumber(2, Label(0))), unapplyLineNumbers) val expected = List( @@ -122,7 +122,7 @@ class BytecodeTest extends BytecodeTesting { Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false) ) - val mainIns = getSingleMethod(module, "main").instructions filter { + val mainIns = getInstructions(module, "main") filter { case _: LineNumber | _: Invoke | _: Jump => true case _ => false } @@ -144,24 +144,24 @@ class BytecodeTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) // t1: no unnecessary GOTOs - assertSameCode(getSingleMethod(c, "t1"), List( + assertSameCode(getMethod(c, "t1"), List( VarOp(ILOAD, 1), Jump(IFEQ, Label(6)), Op(ICONST_1), Jump(GOTO, Label(9)), Label(6), Op(ICONST_2), Label(9), Op(IRETURN))) // t2: no unnecessary GOTOs - assertSameCode(getSingleMethod(c, "t2"), List( + assertSameCode(getMethod(c, "t2"), List( VarOp(ILOAD, 1), IntOp(SIPUSH, 393), Jump(IF_ICMPNE, Label(7)), Op(ICONST_1), Jump(GOTO, Label(10)), Label(7), Op(ICONST_2), Label(10), Op(IRETURN))) // t3: Array == is translated to reference equality, AnyRef == to null checks and equals - assertSameCode(getSingleMethod(c, "t3"), List( + assertSameCode(getMethod(c, "t3"), List( // Array == VarOp(ALOAD, 1), VarOp(ALOAD, 2), Jump(IF_ACMPEQ, Label(23)), // AnyRef == @@ -180,13 +180,13 @@ class BytecodeTest extends BytecodeTesting { Label(13), Op(IRETURN)) // t4: one side is known null, so just a null check on the other - assertSameCode(getSingleMethod(c, "t4"), t4t5) + assertSameCode(getMethod(c, "t4"), t4t5) // t5: one side known null, so just a null check on the other - assertSameCode(getSingleMethod(c, "t5"), t4t5) + assertSameCode(getMethod(c, "t5"), t4t5) // t6: no unnecessary GOTOs - assertSameCode(getSingleMethod(c, "t6"), List( + assertSameCode(getMethod(c, "t6"), List( VarOp(ILOAD, 1), IntOp(BIPUSH, 10), Jump(IF_ICMPNE, Label(7)), VarOp(ILOAD, 2), Jump(IFNE, Label(12)), Label(7), VarOp(ILOAD, 1), Op(ICONST_1), Jump(IF_ICMPEQ, Label(16)), @@ -195,10 +195,10 @@ class BytecodeTest extends BytecodeTesting { Label(19), Op(IRETURN))) // t7: universal equality - assertInvoke(getSingleMethod(c, "t7"), "scala/runtime/BoxesRunTime", "equals") + assertInvoke(getMethod(c, "t7"), "scala/runtime/BoxesRunTime", "equals") // t8: no null checks invoking equals on modules and constants - assertSameCode(getSingleMethod(c, "t8"), List( + assertSameCode(getMethod(c, "t8"), List( Field(GETSTATIC, "scala/collection/immutable/Nil$", "MODULE$", "Lscala/collection/immutable/Nil$;"), VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false), Jump(IFNE, Label(10)), Ldc(LDC, ""), VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false), Jump(IFNE, Label(14)), Label(10), Op(ICONST_1), Jump(GOTO, Label(17)), @@ -207,13 +207,11 @@ class BytecodeTest extends BytecodeTesting { } object forwarderTestUtils { - def findMethods(cls: ClassNode, name: String): List[Method] = cls.methods.iterator.asScala.find(_.name == name).map(convertMethod).toList - import language.implicitConversions implicit def s2c(s: Symbol)(implicit classes: Map[String, ClassNode]): ClassNode = classes(s.name) def checkForwarder(c: ClassNode, target: String) = { - val List(f) = findMethods(c, "f") + val List(f) = getMethods(c, "f") assertSameCode(f, List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, target, "f", "()I", false), Op(IRETURN))) } } @@ -273,7 +271,7 @@ class BytecodeTest extends BytecodeTesting { implicit val classes = compileClasses(code).map(c => (c.name, c)).toMap val noForwarder = List('C1, 'C2, 'C3, 'C4, 'C10, 'C11, 'C12, 'C13, 'C16, 'C17) - for (c <- noForwarder) assertEquals(findMethods(c, "f"), Nil) + for (c <- noForwarder) assertEquals(getMethods(c, "f"), Nil) checkForwarder('C5, "T3") checkForwarder('C6, "T4") @@ -282,10 +280,10 @@ class BytecodeTest extends BytecodeTesting { checkForwarder('C9, "T5") checkForwarder('C14, "T4") checkForwarder('C15, "T5") - assertSameSummary(getSingleMethod('C18, "f"), List(BIPUSH, IRETURN)) + assertSameSummary(getMethod('C18, "f"), List(BIPUSH, IRETURN)) checkForwarder('C19, "T7") - assertSameCode(getSingleMethod('C19, "T7$$super$f"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "C18", "f", "()I", false), Op(IRETURN))) - assertInvoke(getSingleMethod('C20, "clone"), "T8", "clone") // mixin forwarder + assertSameCode(getMethod('C19, "T7$$super$f"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "C18", "f", "()I", false), Op(IRETURN))) + assertInvoke(getMethod('C20, "clone"), "T8", "clone") // mixin forwarder } @Test @@ -297,7 +295,7 @@ class BytecodeTest extends BytecodeTesting { |class C extends T1 with T2 """.stripMargin val List(c, t1, t2) = compileClasses(code) - assertEquals(findMethods(c, "f"), Nil) + assertEquals(getMethods(c, "f"), Nil) } @Test @@ -331,7 +329,7 @@ class BytecodeTest extends BytecodeTesting { implicit val classes = compileClasses(code, List(j1, j2, j3, j4)).map(c => (c.name, c)).toMap val noForwarder = List('K1, 'K2, 'K3, 'K4, 'K5, 'K6, 'K7, 'K8, 'K9, 'K10, 'K11) - for (c <- noForwarder) assertEquals(findMethods(c, "f"), Nil) + for (c <- noForwarder) assertEquals(getMethods(c, "f"), Nil) checkForwarder('K12, "T2") } @@ -340,13 +338,13 @@ class BytecodeTest extends BytecodeTesting { def invocationReceivers(): Unit = { val List(c1, c2, t, u) = compileClasses(invocationReceiversTestCode.definitions("Object")) // mixin forwarder in C1 - assertSameCode(getSingleMethod(c1, "clone"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "T", "clone", "()Ljava/lang/Object;", false), Op(ARETURN))) - assertInvoke(getSingleMethod(c1, "f1"), "T", "clone") - assertInvoke(getSingleMethod(c1, "f2"), "T", "clone") - assertInvoke(getSingleMethod(c1, "f3"), "C1", "clone") - assertInvoke(getSingleMethod(c2, "f1"), "T", "clone") - assertInvoke(getSingleMethod(c2, "f2"), "T", "clone") - assertInvoke(getSingleMethod(c2, "f3"), "C1", "clone") + assertSameCode(getMethod(c1, "clone"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "T", "clone", "()Ljava/lang/Object;", false), Op(ARETURN))) + assertInvoke(getMethod(c1, "f1"), "T", "clone") + assertInvoke(getMethod(c1, "f2"), "T", "clone") + assertInvoke(getMethod(c1, "f3"), "C1", "clone") + assertInvoke(getMethod(c2, "f1"), "T", "clone") + assertInvoke(getMethod(c2, "f2"), "T", "clone") + assertInvoke(getMethod(c2, "f3"), "C1", "clone") val List(c1b, c2b, tb, ub) = compileClasses(invocationReceiversTestCode.definitions("String")) def ms(c: ClassNode, n: String) = c.methods.asScala.toList.filter(_.name == n) @@ -357,11 +355,11 @@ class BytecodeTest extends BytecodeTesting { assert((c1Clone.access | Opcodes.ACC_BRIDGE) != 0) assertSameCode(convertMethod(c1Clone), List(VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "C1", "clone", "()Ljava/lang/String;", false), Op(ARETURN))) - def iv(m: Method) = getSingleMethod(c1b, "f1").instructions.collect({case i: Invoke => i}) - assertSameCode(iv(getSingleMethod(c1b, "f1")), List(Invoke(INVOKEINTERFACE, "T", "clone", "()Ljava/lang/String;", true))) - assertSameCode(iv(getSingleMethod(c1b, "f2")), List(Invoke(INVOKEINTERFACE, "T", "clone", "()Ljava/lang/String;", true))) + def iv(m: Method) = getInstructions(c1b, "f1").collect({case i: Invoke => i}) + assertSameCode(iv(getMethod(c1b, "f1")), List(Invoke(INVOKEINTERFACE, "T", "clone", "()Ljava/lang/String;", true))) + assertSameCode(iv(getMethod(c1b, "f2")), List(Invoke(INVOKEINTERFACE, "T", "clone", "()Ljava/lang/String;", true))) // invokeinterface T.clone in C1 is OK here because it is not an override of Object.clone (different siganture) - assertSameCode(iv(getSingleMethod(c1b, "f3")), List(Invoke(INVOKEINTERFACE, "T", "clone", "()Ljava/lang/String;", true))) + assertSameCode(iv(getMethod(c1b, "f3")), List(Invoke(INVOKEINTERFACE, "T", "clone", "()Ljava/lang/String;", true))) } @Test @@ -395,9 +393,9 @@ class BytecodeTest extends BytecodeTesting { | def f3(j: a.J) = j.f |} """.stripMargin - val List(c) = compileClasses(cC, javaCode = List((aC, "A.java"), (bC, "B.java"), (iC, "I.java"), (jC, "J.java"))) - assertInvoke(getSingleMethod(c, "f1"), "a/B", "f") // receiver needs to be B (A is not accessible in class C, package b) - assertInvoke(getSingleMethod(c, "f3"), "a/J", "f") // receiver needs to be J + val c = compileClass(cC, javaCode = List((aC, "A.java"), (bC, "B.java"), (iC, "I.java"), (jC, "J.java"))) + assertInvoke(getMethod(c, "f1"), "a/B", "f") // receiver needs to be B (A is not accessible in class C, package b) + assertInvoke(getMethod(c, "f3"), "a/J", "f") // receiver needs to be J } @Test @@ -411,11 +409,11 @@ class BytecodeTest extends BytecodeTesting { | |} """.stripMargin - val List(c) = compileClasses(code) - assertInvoke(getSingleMethod(c, "f1"), "[Ljava/lang/String;", "clone") // array descriptor as receiver - assertInvoke(getSingleMethod(c, "f2"), "java/lang/Object", "hashCode") // object receiver - assertInvoke(getSingleMethod(c, "f3"), "java/lang/Object", "hashCode") - assertInvoke(getSingleMethod(c, "f4"), "java/lang/Object", "toString") + val c = compileClass(code) + assertInvoke(getMethod(c, "f1"), "[Ljava/lang/String;", "clone") // array descriptor as receiver + assertInvoke(getMethod(c, "f2"), "java/lang/Object", "hashCode") // object receiver + assertInvoke(getMethod(c, "f3"), "java/lang/Object", "hashCode") + assertInvoke(getMethod(c, "f4"), "java/lang/Object", "toString") } @Test @@ -423,7 +421,7 @@ class BytecodeTest extends BytecodeTesting { // see comment in SpecializeTypes.forwardCtorCall val code = "case class C[@specialized(Int) T](_1: T)" val List(c, cMod, cSpec) = compileClasses(code) - assertSameSummary(getSingleMethod(cSpec, ""), + assertSameSummary(getMethod(cSpec, ""), // pass `null` to super constructor, no box-unbox, no Integer created List(ALOAD, ILOAD, PUTFIELD, ALOAD, ACONST_NULL, "", RETURN)) } diff --git a/test/junit/scala/issues/OptimizedBytecodeTest.scala b/test/junit/scala/issues/OptimizedBytecodeTest.scala index b074215534a5..af1c50acac37 100644 --- a/test/junit/scala/issues/OptimizedBytecodeTest.scala +++ b/test/junit/scala/issues/OptimizedBytecodeTest.scala @@ -27,8 +27,8 @@ class OptimizedBytecodeTest extends BytecodeTesting { | def t(): Unit = while (true) m("...") |} """.stripMargin - val List(c) = compileClasses(code) - assertSameCode(getSingleMethod(c, "t"), List(Label(0), Jump(GOTO, Label(0)))) + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List(Label(0), Jump(GOTO, Label(0)))) } @Test @@ -45,12 +45,12 @@ class OptimizedBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) - assertSameSummary(getSingleMethod(c, "t"), List( + assertSameSummary(getMethod(c, "t"), List( LDC, ASTORE, ALOAD /*0*/, ALOAD /*1*/, "C$$$anonfun$1", IRETURN)) - assertSameSummary(getSingleMethod(c, "C$$$anonfun$1"), List(LDC, "C$$$anonfun$2", IRETURN)) - assertSameSummary(getSingleMethod(c, "C$$$anonfun$2"), List(-1 /*A*/, GOTO /*A*/)) + assertSameSummary(getMethod(c, "C$$$anonfun$1"), List(LDC, "C$$$anonfun$2", IRETURN)) + assertSameSummary(getMethod(c, "C$$$anonfun$2"), List(-1 /*A*/, GOTO /*A*/)) } @Test @@ -72,7 +72,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { |} """.stripMargin val List(c, t, tMod) = compileClasses(code, allowMessage = _.msg.contains("not be exhaustive")) - assertSameSummary(getSingleMethod(c, "t"), List(GETSTATIC, "$qmark$qmark$qmark", ATHROW)) + assertSameSummary(getMethod(c, "t"), List(GETSTATIC, "$qmark$qmark$qmark", ATHROW)) } @Test @@ -109,7 +109,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - compileClasses(code) + compileToBytes(code) } @Test @@ -120,7 +120,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { """.stripMargin val c2 = "class C { def t = warmup.Warmup.filter[Any](x => false) }" val List(c, _, _) = compileClassesSeparately(List(c1, c2), extraArgs = compilerArgs) - assertInvoke(getSingleMethod(c, "t"), "warmup/Warmup$", "filter") + assertInvoke(getMethod(c, "t"), "warmup/Warmup$", "filter") } @Test @@ -134,7 +134,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - compileClasses(code) + compileToBytes(code) } @Test @@ -162,7 +162,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - compileClasses(code) + compileToBytes(code) } @Test @@ -178,7 +178,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - compileClasses(code) + compileToBytes(code) } @Test @@ -217,8 +217,8 @@ class OptimizedBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameSummary(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameSummary(getMethod(c, "t"), List( ALOAD /*1*/, INSTANCEOF /*Some*/, IFNE /*A*/, ALOAD /*0*/, "getInt", POP, -1 /*A*/, BIPUSH, IRETURN)) @@ -236,8 +236,8 @@ class OptimizedBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameSummary(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameSummary(getMethod(c, "t"), List( -1 /*A*/, ILOAD /*1*/, TABLESWITCH, -1, ALOAD, "pr", RETURN, -1, ALOAD, "pr", RETURN, @@ -261,8 +261,8 @@ class OptimizedBytecodeTest extends BytecodeTesting { """.stripMargin val cls = compileClassesSeparately(List(c1, c2), extraArgs = compilerArgs) - val c = cls.find(_.name == "C").get - assertSameSummary(getSingleMethod(c, "t"), List( + val c = findClass(cls, "C") + assertSameSummary(getMethod(c, "t"), List( GETSTATIC, IFNONNULL, ACONST_NULL, ATHROW, // module load and null checks not yet eliminated -1, ICONST_1, GETSTATIC, IFNONNULL, ACONST_NULL, ATHROW, -1, ICONST_2, IADD, IRETURN)) @@ -299,11 +299,11 @@ class OptimizedBytecodeTest extends BytecodeTesting { | def f2b() = identity(wrapper2(5)) // not inlined |} """.stripMargin - val List(c) = compileClasses(code, allowMessage = _.msg.contains("exception handler declared in the inlined method")) - assertInvoke(getSingleMethod(c, "f1a"), "C", "C$$$anonfun$1") - assertInvoke(getSingleMethod(c, "f1b"), "C", "wrapper1") - assertInvoke(getSingleMethod(c, "f2a"), "C", "C$$$anonfun$3") - assertInvoke(getSingleMethod(c, "f2b"), "C", "wrapper2") + val c = compileClass(code, allowMessage = _.msg.contains("exception handler declared in the inlined method")) + assertInvoke(getMethod(c, "f1a"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "f1b"), "C", "wrapper1") + assertInvoke(getMethod(c, "f2a"), "C", "C$$$anonfun$3") + assertInvoke(getMethod(c, "f2b"), "C", "wrapper2") } @Test @@ -317,8 +317,8 @@ class OptimizedBytecodeTest extends BytecodeTesting { | def t = mbarray_apply_minibox(null, 0) |} """.stripMargin - val List(c) = compileClasses(code) - assertNoInvoke(getSingleMethod(c, "t")) + val c = compileClass(code) + assertNoInvoke(getMethod(c, "t")) } @Test @@ -336,7 +336,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { |class Listt """.stripMargin val List(c, nil, nilMod, listt) = compileClasses(code) - assertInvoke(getSingleMethod(c, "t"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "t"), "C", "C$$$anonfun$1") } @Test @@ -355,13 +355,13 @@ class OptimizedBytecodeTest extends BytecodeTesting { |} """.stripMargin val List(c, f) = compileClasses(code) - assertInvoke(getSingleMethod(c, "crash"), "C", "map") + assertInvoke(getMethod(c, "crash"), "C", "map") } @Test def optimiseEnablesNewOpt(): Unit = { val code = """class C { def t = (1 to 10) foreach println }""" - val List(c) = readAsmClasses(newCompiler(extraArgs = "-optimise -deprecation").compile(code, allowMessage = _.msg.contains("is deprecated"))) - assertInvoke(getSingleMethod(c, "t"), "C", "C$$$anonfun$1") // range-foreach inlined from classpath + val List(c) = readAsmClasses(newCompiler(extraArgs = "-optimise -deprecation").compileToBytes(code, allowMessage = _.msg.contains("is deprecated"))) + assertInvoke(getMethod(c, "t"), "C", "C$$$anonfun$1") // range-foreach inlined from classpath } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala index b538ae0bc603..c9a958ee4f4d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala @@ -26,7 +26,7 @@ class DefaultMethodTest extends BytecodeTesting { case _ => super.transform(tree) } } - val asmClasses: List[ClassNode] = readAsmClasses(compiler.compileTransformed(code, Nil, makeFooDefaultMethod.transform(_))) + val asmClasses: List[ClassNode] = compiler.compileClassesTransformed(code, Nil, makeFooDefaultMethod.transform(_)) val foo = asmClasses.head.methods.iterator.asScala.toList.last assertTrue("default method should not be abstract", (foo.access & Opcodes.ACC_ABSTRACT) == 0) assertTrue("default method body emitted", foo.instructions.size() > 0) diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala index 65b4264ee9e3..7fdfb315779d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala @@ -17,7 +17,7 @@ class DirectCompileTest extends BytecodeTesting { @Test def testCompile(): Unit = { - val List(("C.class", bytes)) = compile( + val List(("C.class", bytes)) = compileToBytes( """class C { | def f = 1 |} @@ -45,21 +45,19 @@ class DirectCompileTest extends BytecodeTesting { """def f = 10 |def g = f """.stripMargin) - assertTrue(f.name == "f") - assertTrue(g.name == "g") - assertSameCode(instructionsFromMethod(f).dropNonOp, + assertSameCode(f.instructions.dropNonOp, List(IntOp(BIPUSH, 10), Op(IRETURN))) - assertSameCode(instructionsFromMethod(g).dropNonOp, + assertSameCode(g.instructions.dropNonOp, List(VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "C", "f", "()I", itf = false), Op(IRETURN))) } @Test def testDropNonOpAliveLabels(): Unit = { // makes sure that dropNoOp doesn't drop labels that are being used - val List(f) = compileMethods("""def f(x: Int) = if (x == 0) "a" else "b"""") - assertSameCode(instructionsFromMethod(f).dropLinesFrames, List( + val is = compileInstructions("""def f(x: Int) = if (x == 0) "a" else "b"""") + assertSameCode(is.dropLinesFrames, List( Label(0), VarOp(ILOAD, 1), Op(ICONST_0), @@ -79,7 +77,7 @@ class DirectCompileTest extends BytecodeTesting { val codeA = "class A { def f = 1 }" val codeB = "class B extends A { def g = f }" val List(a, b) = compileClassesSeparately(List(codeA, codeB)) - val ins = getSingleMethod(b, "g").instructions + val ins = getInstructions(b, "g") assert(ins exists { case Invoke(_, "B", "f", _, _) => true case _ => false @@ -88,6 +86,6 @@ class DirectCompileTest extends BytecodeTesting { @Test def compileErroneous(): Unit = { - compileClasses("class C { def f: String = 1 }", allowMessage = _.msg contains "type mismatch") + compileToBytes("class C { def f: String = 1 }", allowMessage = _.msg contains "type mismatch") } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala b/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala index 22ced47a02f3..ac2aab01dc4b 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala @@ -13,7 +13,7 @@ class IndyLambdaTest extends BytecodeTesting { @Test def boxingBridgeMethodUsedSelectively(): Unit = { def implMethodDescriptorFor(code: String): String = { - val method = compileMethods(s"""def f = $code """).find(_.name == "f").get + val method = compileAsmMethods(s"""def f = $code """).find(_.name == "f").get val x = method.instructions.iterator.asScala.toList x.flatMap { case insn : InvokeDynamicInsnNode => insn.bsmArgs.collect { case h : Handle => h.getDesc } @@ -46,17 +46,17 @@ class IndyLambdaTest extends BytecodeTesting { assertEquals("(I)I", implMethodDescriptorFor("(x: Int) => x")) // non-builtin sams are like specialized functions - compileClasses("class VC(private val i: Int) extends AnyVal; trait FunVC { def apply(a: VC): VC }") + compileToBytes("class VC(private val i: Int) extends AnyVal; trait FunVC { def apply(a: VC): VC }") assertEquals("(I)I", implMethodDescriptorFor("((x: VC) => x): FunVC")) - compileClasses("trait Fun1[T, U] { def apply(a: T): U }") + compileToBytes("trait Fun1[T, U] { def apply(a: T): U }") assertEquals(s"($obj)$str", implMethodDescriptorFor("(x => x.toString): Fun1[Int, String]")) assertEquals(s"($obj)$obj", implMethodDescriptorFor("(x => println(x)): Fun1[Int, Unit]")) assertEquals(s"($obj)$str", implMethodDescriptorFor("((x: VC) => \"\") : Fun1[VC, String]")) assertEquals(s"($str)$obj", implMethodDescriptorFor("((x: String) => new VC(0)) : Fun1[String, VC]")) - compileClasses("trait Coll[A, Repr] extends Any") - compileClasses("final class ofInt(val repr: Array[Int]) extends AnyVal with Coll[Int, Array[Int]]") + compileToBytes("trait Coll[A, Repr] extends Any") + compileToBytes("final class ofInt(val repr: Array[Int]) extends AnyVal with Coll[Int, Array[Int]]") assertEquals(s"([I)$obj", implMethodDescriptorFor("((xs: Array[Int]) => new ofInt(xs)): Array[Int] => Coll[Int, Array[Int]]")) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala index d7c1f191d0f9..2bcbcc870cf5 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala @@ -39,13 +39,13 @@ class IndySammyTest extends BytecodeTesting { def test(from: String, to: String, arg: String, body: String => String = x => x) (expectedSig: String, lamBody: List[Instruction], appArgs: List[Instruction], ret: Instruction) (allowMessage: StoreReporter#Info => Boolean = _ => false) = { - val cls = compileClasses(s"${classPrologue(from, to)}") - val methodNodes = compileMethods(lamDef(from, to, body) +";"+ appDef(arg), allowMessage) + val List(funClass, vcClass, vcCompanion) = compileClasses(s"${classPrologue(from, to)}") + val c = compileClass(s"class C { ${lamDef(from, to, body)}; ${appDef(arg)} }", allowMessage = allowMessage) - val applySig = cls.head.methods.get(0).desc - val anonfun = methodNodes.find(_.name contains "$anonfun$").map(convertMethod).get - val lamInsn = methodNodes.find(_.name == "lam").map(instructionsFromMethod).get.dropNonOp - val applyInvoke = methodNodes.find(_.name == "app").map(convertMethod).get + val applySig = getAsmMethod(funClass, "apply").desc + val anonfun = getMethod(c, "C$$$anonfun$1") + val lamInsn = getInstructions(c, "lam").dropNonOp + val applyInvoke = getMethod(c, "app") assertEquals(expectedSig, applySig) assert(lamInsn.length == 2 && lamInsn.head.isInstanceOf[InvokeDynamic], lamInsn) @@ -140,7 +140,7 @@ class IndySammyTest extends BytecodeTesting { // Tests ThisReferringMethodsTraverser @Test def testStaticIfNoThisReference: Unit = { - val methodNodes = compileMethods("def foo = () => () => () => 42") + val methodNodes = compileAsmMethods("def foo = () => () => () => 42") methodNodes.forall(m => !m.name.contains("anonfun") || (m.access & ACC_STATIC) == ACC_STATIC) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala index f231df8af060..af2c8f9ce008 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/StringConcatTest.scala @@ -50,9 +50,9 @@ class StringConcatTest extends BytecodeTesting { | chrs: Array[Char]) = this + str + v + z + c + b + s + i + f + l + d + sbuf + chsq + chrs |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) - def invokeNameDesc(m: String): List[String] = getSingleMethod(c, m).instructions collect { + def invokeNameDesc(m: String): List[String] = getInstructions(c, m) collect { case Invoke(_, _, name, desc, _) => name + desc } assertEquals(invokeNameDesc("t1"), List( diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala index 358a46102605..b0a86dfd28b3 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala @@ -24,7 +24,7 @@ class NullnessAnalyzerTest extends BytecodeTesting { def newNullnessAnalyzer(methodNode: MethodNode, classInternalName: InternalName = "C") = new AsmAnalyzer(methodNode, classInternalName, new NullnessAnalyzer(global.genBCode.bTypes)) def testNullness(analyzer: AsmAnalyzer[NullnessValue], method: MethodNode, query: String, index: Int, nullness: NullnessValue): Unit = { - for (i <- findInstr(method, query)) { + for (i <- findInstrs(method, query)) { val r = analyzer.frameAt(i).getValue(index) assertTrue(s"Expected: $nullness, found: $r. At instr ${textify(i)}", nullness == r) } @@ -50,7 +50,7 @@ class NullnessAnalyzerTest extends BytecodeTesting { @Test def showNullnessFramesTest(): Unit = { - val List(m) = compileMethods("def f = this.toString") + val m = compileAsmMethod("def f = this.toString") // NOTE: the frame for an instruction represents the state *before* executing that instr. // So in the frame for `ALOAD 0`, the stack is still empty. @@ -68,14 +68,14 @@ class NullnessAnalyzerTest extends BytecodeTesting { @Test def thisNonNull(): Unit = { - val List(m) = compileMethods("def f = this.toString") + val m = compileAsmMethod("def f = this.toString") val a = newNullnessAnalyzer(m) testNullness(a, m, "ALOAD 0", 0, NotNullValue) } @Test def instanceMethodCall(): Unit = { - val List(m) = compileMethods("def f(a: String) = a.trim") + val m = compileAsmMethod("def f(a: String) = a.trim") val a = newNullnessAnalyzer(m) testNullness(a, m, "INVOKEVIRTUAL java/lang/String.trim", 1, UnknownValue1) testNullness(a, m, "ARETURN", 1, NotNullValue) @@ -83,7 +83,7 @@ class NullnessAnalyzerTest extends BytecodeTesting { @Test def constructorCall(): Unit = { - val List(m) = compileMethods("def f = { val a = new Object; a.toString }") + val m = compileAsmMethod("def f = { val a = new Object; a.toString }") val a = newNullnessAnalyzer(m) // for reference, the output of showAllNullnessFrames(a, m) - note that the frame represents the state *before* executing the instr. @@ -108,7 +108,7 @@ class NullnessAnalyzerTest extends BytecodeTesting { @Test def explicitNull(): Unit = { - val List(m) = compileMethods("def f = { var a: Object = null; a }") + val m = compileAsmMethod("def f = { var a: Object = null; a }") val a = newNullnessAnalyzer(m) for ((insn, index, nullness) <- List( ("+ACONST_NULL", 2, NullValue), @@ -119,14 +119,14 @@ class NullnessAnalyzerTest extends BytecodeTesting { @Test def stringLiteralsNotNull(): Unit = { - val List(m) = compileMethods("""def f = { val a = "hi"; a.trim }""") + val m = compileAsmMethod("""def f = { val a = "hi"; a.trim }""") val a = newNullnessAnalyzer(m) testNullness(a, m, "+ASTORE 1", 1, NotNullValue) } @Test def newArraynotNull() { - val List(m) = compileMethods("def f = { val a = new Array[Int](2); a(0) }") + val m = compileAsmMethod("def f = { val a = new Array[Int](2); a(0) }") val a = newNullnessAnalyzer(m) testNullness(a, m, "+NEWARRAY T_INT", 2, NotNullValue) // new array on stack testNullness(a, m, "+ASTORE 1", 1, NotNullValue) // local var (a) @@ -144,7 +144,7 @@ class NullnessAnalyzerTest extends BytecodeTesting { | a.toString |} """.stripMargin - val List(m) = compileMethods(code) + val m = compileAsmMethod(code) val a = newNullnessAnalyzer(m) val toSt = "+INVOKEVIRTUAL java/lang/Object.toString" testNullness(a, m, toSt, 3, UnknownValue1) @@ -170,7 +170,7 @@ class NullnessAnalyzerTest extends BytecodeTesting { | // d is null here, assinged in both branches. |} """.stripMargin - val List(m) = compileMethods(code) + val m = compileAsmMethod(code) val a = newNullnessAnalyzer(m) val trim = "INVOKEVIRTUAL java/lang/String.trim" @@ -206,7 +206,7 @@ class NullnessAnalyzerTest extends BytecodeTesting { | a.asInstanceOf[String].trim // the stack value (LOAD of local a) is still not-null after the CHECKCAST |} """.stripMargin - val List(m) = compileMethods(code) + val m = compileAsmMethod(code) val a = newNullnessAnalyzer(m) val instof = "+INSTANCEOF" diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala index be10370312b5..fc2678523764 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala @@ -49,9 +49,9 @@ class ProdConsAnalyzerTest extends BytecodeTesting { @Test def parameters(): Unit = { - val List(m) = compileMethods("def f = this.toString") + val m = compileAsmMethod("def f = this.toString") val a = new ProdConsAnalyzer(m, "C") - val call = findInstr(m, "INVOKEVIRTUAL").head + val call = findInstr(m, "INVOKEVIRTUAL") testSingleInsn(a.producersForValueAt(call, 1), "ALOAD 0") // producer of stack value testSingleInsn(a.producersForInputsOf(call), "ALOAD 0") @@ -84,55 +84,55 @@ class ProdConsAnalyzerTest extends BytecodeTesting { m.maxStack = 1 val a = new ProdConsAnalyzer(m, "C") - val ifne = findInstr(m, "IFNE").head + val ifne = findInstr(m, "IFNE") testSingleInsn(a.producersForValueAt(ifne, 1), "ParameterProducer") - val ret = findInstr(m, "IRETURN").head + val ret = findInstr(m, "IRETURN") testMultiInsns(a.producersForValueAt(ret, 1), List("ParameterProducer", "ISTORE 1")) } @Test def branching(): Unit = { - val List(m) = compileMethods("def f(x: Int) = { var a = x; if (a == 0) a = 12; a }") + val m = compileAsmMethod("def f(x: Int) = { var a = x; if (a == 0) a = 12; a }") val a = new ProdConsAnalyzer(m, "C") - val List(ret) = findInstr(m, "IRETURN") + val ret = findInstr(m, "IRETURN") testMultiInsns(a.producersForValueAt(ret, 2), List("ISTORE 2", "ISTORE 2")) testMultiInsns(a.initialProducersForValueAt(ret, 2), List("BIPUSH 12", "ParameterProducer")) - val List(bipush) = findInstr(m, "BIPUSH 12") + val bipush = findInstr(m, "BIPUSH 12") testSingleInsn(a.consumersOfOutputsFrom(bipush), "ISTORE 2") testSingleInsn(a.ultimateConsumersOfValueAt(bipush.getNext, 3), "IRETURN") } @Test def checkCast(): Unit = { - val List(m) = compileMethods("def f(o: Object) = o.asInstanceOf[String]") + val m = compileAsmMethod("def f(o: Object) = o.asInstanceOf[String]") val a = new ProdConsAnalyzer(m, "C") - assert(findInstr(m, "CHECKCAST java/lang/String").length == 1) + assert(findInstrs(m, "CHECKCAST java/lang/String").length == 1) - val List(ret) = findInstr(m, "ARETURN") + val ret = findInstr(m, "ARETURN") testSingleInsn(a.initialProducersForInputsOf(ret), "ParameterProducer(1)") } @Test def instanceOf(): Unit = { - val List(m) = compileMethods("def f(o: Object) = o.isInstanceOf[String]") + val m = compileAsmMethod("def f(o: Object) = o.isInstanceOf[String]") val a = new ProdConsAnalyzer(m, "C") - assert(findInstr(m, "INSTANCEOF java/lang/String").length == 1) + assert(findInstrs(m, "INSTANCEOF java/lang/String").length == 1) - val List(ret) = findInstr(m, "IRETURN") + val ret = findInstr(m, "IRETURN") testSingleInsn(a.initialProducersForInputsOf(ret), "INSTANCEOF") } @Test def unInitLocal(): Unit = { - val List(m) = compileMethods("def f(b: Boolean) = { if (b) { var a = 0; println(a) }; 1 }") + val m = compileAsmMethod("def f(b: Boolean) = { if (b) { var a = 0; println(a) }; 1 }") val a = new ProdConsAnalyzer(m, "C") - val List(store) = findInstr(m, "ISTORE") - val List(call) = findInstr(m, "INVOKEVIRTUAL") - val List(ret) = findInstr(m, "IRETURN") + val store = findInstr(m, "ISTORE") + val call = findInstr(m, "INVOKEVIRTUAL") + val ret = findInstr(m, "IRETURN") testSingleInsn(a.producersForValueAt(store, 2), "UninitializedLocalProducer(2)") testSingleInsn(a.producersForValueAt(call, 2), "ISTORE") @@ -141,11 +141,11 @@ class ProdConsAnalyzerTest extends BytecodeTesting { @Test def dupCopying(): Unit = { - val List(m) = compileMethods("def f = new Object") + val m = compileAsmMethod("def f = new Object") val a = new ProdConsAnalyzer(m, "C") - val List(newO) = findInstr(m, "NEW") - val List(constr) = findInstr(m, "INVOKESPECIAL") + val newO = findInstr(m, "NEW") + val constr = findInstr(m, "INVOKESPECIAL") testSingleInsn(a.producersForInputsOf(constr), "DUP") testSingleInsn(a.initialProducersForInputsOf(constr), "NEW") @@ -170,11 +170,11 @@ class ProdConsAnalyzerTest extends BytecodeTesting { m.maxStack = 4 val a = new ProdConsAnalyzer(m, "C") - val List(dup2) = findInstr(m, "DUP2") - val List(add) = findInstr(m, "IADD") - val List(swap) = findInstr(m, "SWAP") - val List(store) = findInstr(m, "ISTORE") - val List(ret) = findInstr(m, "IRETURN") + val dup2 = findInstr(m, "DUP2") + val add = findInstr(m, "IADD") + val swap = findInstr(m, "SWAP") + val store = findInstr(m, "ISTORE") + val ret = findInstr(m, "IRETURN") testMultiInsns(a.producersForInputsOf(dup2), List("ILOAD", "ILOAD")) testSingleInsn(a.consumersOfValueAt(dup2.getNext, 4), "IADD") @@ -205,9 +205,9 @@ class ProdConsAnalyzerTest extends BytecodeTesting { m.maxStack = 1 val a = new ProdConsAnalyzer(m, "C") - val List(inc) = findInstr(m, "IINC") - val List(load) = findInstr(m, "ILOAD") - val List(ret) = findInstr(m, "IRETURN") + val inc = findInstr(m, "IINC") + val load = findInstr(m, "ILOAD") + val ret = findInstr(m, "IRETURN") testSingleInsn(a.producersForInputsOf(inc), "ParameterProducer(1)") testSingleInsn(a.consumersOfOutputsFrom(inc), "ILOAD") @@ -223,12 +223,12 @@ class ProdConsAnalyzerTest extends BytecodeTesting { @Test def copyingInsns(): Unit = { - val List(m) = compileMethods("def f = 0l.asInstanceOf[Int]") + val m = compileAsmMethod("def f = 0l.asInstanceOf[Int]") val a = new ProdConsAnalyzer(m, "C") - val List(cnst) = findInstr(m, "LCONST_0") - val List(l2i) = findInstr(m, "L2I") // l2i is not a copying instruction - val List(ret) = findInstr(m, "IRETURN") + val cnst = findInstr(m, "LCONST_0") + val l2i = findInstr(m, "L2I") // l2i is not a copying instruction + val ret = findInstr(m, "IRETURN") testSingleInsn(a.consumersOfOutputsFrom(cnst), "L2I") testSingleInsn(a.ultimateConsumersOfOutputsFrom(cnst), "L2I") @@ -264,10 +264,10 @@ class ProdConsAnalyzerTest extends BytecodeTesting { m.maxStack = 2 val a = new ProdConsAnalyzer(m, "C") - val List(iadd) = findInstr(m, "IADD") + val iadd = findInstr(m, "IADD") val firstLoad = iadd.getPrevious.getPrevious assert(firstLoad.getOpcode == ILOAD) - val secondLoad = findInstr(m, "ISTORE").head.getPrevious + val secondLoad = findInstr(m, "ISTORE").getPrevious assert(secondLoad.getOpcode == ILOAD) testSingleInsn(a.producersForValueAt(iadd, 2), "ILOAD") diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala index a5fb1e7d17d6..025248ac2880 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala @@ -32,17 +32,17 @@ class AnalyzerTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) val a = new AliasingAnalyzer(new BasicInterpreter) - val f = findAsmMethod(c, "f") + val f = getAsmMethod(c, "f") a.analyze("C", f) - val List(_, i2l) = findInstr(f, "I2L") + val List(_, i2l) = findInstrs(f, "I2L") val aliasesAtI2l = a.frameAt(i2l, f).asInstanceOf[AliasingFrame[_]].aliases assertEquals(aliasesAtI2l(1).iterator.toList, List(1, 8, 9)) // a, e and stack top assertEquals(aliasesAtI2l(4).iterator.toList, List(4, 6)) - val List(add) = findInstr(f, "LADD") + val add = findInstr(f, "LADD") val aliasesAtAdd = a.frameAt(add, f).asInstanceOf[AliasingFrame[_]].aliases assertEquals(aliasesAtAdd(1).iterator.toList, List(1, 8)) // after i2l the value on the stack is no longer an alias assertEquals(aliasesAtAdd(4).iterator.toList, List(4, 6, 10)) // c, d and stack top diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala index 900608837f42..630416a92582 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala @@ -104,10 +104,10 @@ class CallGraphTest extends BytecodeTesting { val List(cCls, cMod, dCls, testCls) = compile(code, checkMsg) assert(msgCount == 6, msgCount) - val List(cf1, cf2, cf3, cf4, cf5, cf6, cf7) = findAsmMethods(cCls, _.startsWith("f")) - val List(df1, df3) = findAsmMethods(dCls, _.startsWith("f")) - val g1 = findAsmMethod(cMod, "g1") - val List(t1, t2) = findAsmMethods(testCls, _.startsWith("t")) + val List(cf1, cf2, cf3, cf4, cf5, cf6, cf7) = getAsmMethods(cCls, _.startsWith("f")) + val List(df1, df3) = getAsmMethods(dCls, _.startsWith("f")) + val g1 = getAsmMethod(cMod, "g1") + val List(t1, t2) = getAsmMethods(testCls, _.startsWith("t")) val List(cf1Call, cf2Call, cf3Call, cf4Call, cf5Call, cf6Call, cf7Call, cg1Call) = callsInMethod(t1) val List(df1Call, df2Call, df3Call, df4Call, df5Call, df6Call, df7Call, dg1Call) = callsInMethod(t2) @@ -143,7 +143,7 @@ class CallGraphTest extends BytecodeTesting { |} """.stripMargin val List(c) = compile(code) - val m = findAsmMethod(c, "m") + val m = getAsmMethod(c, "m") val List(fn) = callsInMethod(m) val forNameMeth = byteCodeRepository.methodNode("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;").get._1 val classTp = classBTypeFromInternalName("java/lang/Class") diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala index ddd95ddc0260..218b02f82259 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala @@ -26,9 +26,9 @@ class ClosureOptimizerTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) - val t = findAsmMethod(c, "t") - val List(bodyCall) = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Nothing$") + val c = compileClass(code) + val t = getAsmMethod(c, "t") + val bodyCall = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Nothing$") assert(bodyCall.getNext.getOpcode == ATHROW) } @@ -42,9 +42,9 @@ class ClosureOptimizerTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) - val t = findAsmMethod(c, "t") - val List(bodyCall) = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Null$") + val c = compileClass(code) + val t = getAsmMethod(c, "t") + val bodyCall = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Null$") assert(bodyCall.getNext.getOpcode == POP) assert(bodyCall.getNext.getNext.getOpcode == ACONST_NULL) } @@ -59,8 +59,8 @@ class ClosureOptimizerTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameCode(getSingleMethod(c, "t"), + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List(VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "scala/collection/immutable/List", "head", "()Ljava/lang/Object;", false), TypeOp(CHECKCAST, "java/lang/String"), Invoke(INVOKESTATIC, "C", "C$$$anonfun$1", "(Ljava/lang/String;)Ljava/lang/String;", false), Op(ARETURN))) @@ -80,7 +80,7 @@ class ClosureOptimizerTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameSummary(getSingleMethod(c, "t"), List(NEW, DUP, LDC, "", ATHROW)) + val c = compileClass(code) + assertSameSummary(getMethod(c, "t"), List(NEW, DUP, LDC, "", ATHROW)) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala index 50e3af6ee5ef..c3748a05bd46 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala @@ -56,8 +56,8 @@ class CompactLocalVariablesTest extends ClearAfterClass { |} |""".stripMargin - val List(noCompact) = noCompactVarsCompiler.compileMethods(code) - val List(withCompact) = methodOptCompiler.compileMethods(code) + val noCompact = noCompactVarsCompiler.compileAsmMethod(code) + val withCompact = methodOptCompiler.compileAsmMethod(code) // code is the same, except for local var indices assertTrue(noCompact.instructions.size == withCompact.instructions.size) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala index 9fb4aa1658d4..3324058cb762 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala @@ -60,8 +60,8 @@ class EmptyExceptionHandlersTest extends BytecodeTesting { def eliminateUnreachableHandler(): Unit = { val code = "def f: Unit = try { } catch { case _: Exception => println(0) }; println(1)" - assertTrue(noOptCompiler.singleMethod(code).handlers.length == 1) - val optMethod = dceCompiler.singleMethod(code) + assertTrue(noOptCompiler.compileMethod(code).handlers.length == 1) + val optMethod = dceCompiler.compileMethod(code) assertTrue(optMethod.handlers.isEmpty) val code2 = @@ -73,7 +73,7 @@ class EmptyExceptionHandlersTest extends BytecodeTesting { | println(2) |}""".stripMargin - assertTrue(dceCompiler.singleMethod(code2).handlers.isEmpty) + assertTrue(dceCompiler.compileMethod(code2).handlers.isEmpty) } @Test @@ -85,6 +85,6 @@ class EmptyExceptionHandlersTest extends BytecodeTesting { | catch { case _: Exception => 2 } |}""".stripMargin - assertTrue(dceCompiler.singleMethod(code).handlers.length == 1) + assertTrue(dceCompiler.compileMethod(code).handlers.length == 1) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index 876c47a84ef1..f0913f36318d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -38,7 +38,7 @@ class InlineWarningTest extends BytecodeTesting { "C::m1()I is annotated @inline but cannot be inlined: the method is not final and may be overridden", "T::m2()I is annotated @inline but cannot be inlined: the method is not final and may be overridden", "D::m2()I is annotated @inline but cannot be inlined: the method is not final and may be overridden") - compile(code, allowMessage = i => {count += 1; warns.exists(i.msg contains _)}) + compileToBytes(code, allowMessage = i => {count += 1; warns.exists(i.msg contains _)}) assert(count == 4, count) } @@ -53,7 +53,7 @@ class InlineWarningTest extends BytecodeTesting { """.stripMargin var c = 0 - compile(code, allowMessage = i => {c += 1; i.msg contains "operand stack at the callsite in C::t1()V contains more values"}) + compileToBytes(code, allowMessage = i => {c += 1; i.msg contains "operand stack at the callsite in C::t1()V contains more values"}) assert(c == 1, c) } @@ -83,14 +83,14 @@ class InlineWarningTest extends BytecodeTesting { |Note that the parent class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin) var c = 0 - val List(b) = compile(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.tail.exists(i.msg contains _)}) + val List(b) = compileToBytes(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.tail.exists(i.msg contains _)}) assert(c == 1, c) // no warnings here - newCompiler(extraArgs = s"$optCp -Yopt-warnings:none").compile(scalaCode, List((javaCode, "A.java"))) + newCompiler(extraArgs = s"$optCp -Yopt-warnings:none").compileToBytes(scalaCode, List((javaCode, "A.java"))) c = 0 - newCompiler(extraArgs = s"$optCp -Yopt-warnings:no-inline-mixed").compile(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) + newCompiler(extraArgs = s"$optCp -Yopt-warnings:no-inline-mixed").compileToBytes(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) assert(c == 2, c) } @@ -117,7 +117,7 @@ class InlineWarningTest extends BytecodeTesting { |that would cause an IllegalAccessError when inlined into class N""".stripMargin var c = 0 - compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn }) assert(c == 1, c) } @@ -136,7 +136,7 @@ class InlineWarningTest extends BytecodeTesting { | def t(a: M) = a.f(x => x + 1) |} """.stripMargin - compile(code, allowMessage = _ => false) // no warnings allowed + compileToBytes(code, allowMessage = _ => false) // no warnings allowed val warn = """M::f(Lscala/Function1;)I could not be inlined: @@ -144,7 +144,7 @@ class InlineWarningTest extends BytecodeTesting { |that would cause an IllegalAccessError when inlined into class N""".stripMargin var c = 0 - compilerWarnAll.compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + compilerWarnAll.compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn }) assert(c == 1, c) } @@ -165,7 +165,7 @@ class InlineWarningTest extends BytecodeTesting { |does not have the same strictfp mode as the callee C::f()I.""".stripMargin var c = 0 - compile(code, allowMessage = i => { c += 1; i.msg contains warn }) + compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn }) assert(c == 1, c) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala index 8a44f12045c1..e7c3bab62f6b 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala @@ -37,9 +37,9 @@ class InlinerSeparateCompilationTest { val warn = "T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" val List(c, o, oMod, t) = compileClassesSeparately(List(codeA, codeB), args + " -Yopt-warnings", _.msg contains warn) - assertInvoke(getSingleMethod(c, "t1"), "T", "f") - assertNoInvoke(getSingleMethod(c, "t2")) - assertNoInvoke(getSingleMethod(c, "t3")) + assertInvoke(getMethod(c, "t1"), "T", "f") + assertNoInvoke(getMethod(c, "t2")) + assertNoInvoke(getMethod(c, "t3")) } @Test @@ -57,7 +57,7 @@ class InlinerSeparateCompilationTest { """.stripMargin val List(c, t) = compileClassesSeparately(List(codeA, codeB), args) - assertNoInvoke(getSingleMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t1")) } @Test @@ -80,7 +80,7 @@ class InlinerSeparateCompilationTest { """.stripMargin val List(c, t, u) = compileClassesSeparately(List(codeA, codeB), args) - for (m <- List("t1", "t2", "t3")) assertNoInvoke(getSingleMethod(c, m)) + for (m <- List("t1", "t2", "t3")) assertNoInvoke(getMethod(c, m)) } @Test @@ -101,7 +101,7 @@ class InlinerSeparateCompilationTest { """.stripMargin val List(a, t) = compileClassesSeparately(List(codeA, assembly), args) - assertNoInvoke(getSingleMethod(t, "f")) - assertNoInvoke(getSingleMethod(a, "n")) + assertNoInvoke(getMethod(t, "f")) + assertNoInvoke(getMethod(a, "n")) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 4db7695fddd3..24e889cf186e 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -39,7 +39,7 @@ class InlinerTest extends BytecodeTesting { def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { notPerRun.foreach(_.clear()) - compileClasses(scalaCode, javaCode, allowMessage) + compileToBytes(scalaCode, javaCode, allowMessage) // Use the class nodes stored in the byteCodeRepository. The ones returned by compileClasses are not the same, // these are created new from the classfile byte array. They are completely separate instances which cannot // be used to look up methods / callsites in the callGraph hash maps for example. @@ -60,7 +60,7 @@ class InlinerTest extends BytecodeTesting { def gMethAndFCallsite(code: String, mod: ClassNode => Unit = _ => ()) = { val List(c) = compile(code) mod(c) - val gMethod = findAsmMethod(c, "g") + val gMethod = getAsmMethod(c, "g") val fCall = getCallsite(gMethod, "f") (gMethod, fCall) } @@ -148,7 +148,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val can = canInlineTest(code, cls => { - val f = cls.methods.asScala.find(_.name == "f").get + val f = getAsmMethod(cls, "f") f.access |= ACC_SYNCHRONIZED }) assert(can.nonEmpty && can.get.isInstanceOf[SynchronizedMethod], can) @@ -197,7 +197,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c, d) = compile(code) - val hMeth = findAsmMethod(d, "h") + val hMeth = getAsmMethod(d, "h") val gCall = getCallsite(hMeth, "g") val r = inliner.canInlineBody(gCall) assert(r.nonEmpty && r.get.isInstanceOf[IllegalAccessInstruction], r) @@ -214,7 +214,7 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(cCls) = compile(code) - val instructions = getSingleMethod(cCls, "test").instructions + val instructions = getInstructions(cCls, "test") assert(instructions.contains(Op(ICONST_0)), instructions.stringLines) assert(!instructions.contains(Op(ICONST_1)), instructions) } @@ -280,7 +280,7 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c, _, _) = compile(code) - val ins = getSingleMethod(c, "f").instructions + val ins = getInstructions(c, "f") val invokeSysArraycopy = Invoke(INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", false) assert(ins contains invokeSysArraycopy, ins.stringLines) } @@ -312,7 +312,7 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c, t) = compile(code) - assertNoInvoke(getSingleMethod(c, "g")) + assertNoInvoke(getMethod(c, "g")) } @Test @@ -325,7 +325,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) // no more invoke, f is inlined - assertNoInvoke(getSingleMethod(c, "g")) + assertNoInvoke(getMethod(c, "g")) } @Test @@ -337,7 +337,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - val fMeth = findAsmMethod(c, "f") + val fMeth = getAsmMethod(c, "f") val call = getCallsite(fMeth, "lowestOneBit") val warning = inliner.canInlineBody(call) @@ -376,7 +376,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin // use a compiler without local optimizations (cleanups) - val List(c) = inlineOnlyCompiler.compileClasses(code) + val c = inlineOnlyCompiler.compileClass(code) val ms @ List(f1, f2, g1, g2) = c.methods.asScala.filter(_.name.length == 2).toList // stack height at callsite of f1 is 1, so max of g1 after inlining is max of f1 + 1 @@ -421,7 +421,7 @@ class InlinerTest extends BytecodeTesting { var c = 0 val List(b) = compile(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; i.msg contains warn}) assert(c == 1, c) - val ins = getSingleMethod(b, "g").instructions + val ins = getInstructions(b, "g") val invokeFlop = Invoke(INVOKEVIRTUAL, "B", "flop", "()I", false) assert(ins contains invokeFlop, ins.stringLines) } @@ -441,8 +441,8 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c, t) = compile(code) // both are just `return 1`, no more calls - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) } @Test @@ -460,8 +460,8 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c, t, u) = compile(code) - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) } @Test @@ -481,8 +481,8 @@ class InlinerTest extends BytecodeTesting { var count = 0 val List(c, t) = compile(code, allowMessage = i => {count += 1; warns.exists(i.msg contains _)}) assert(count == 2, count) - assertInvoke(getSingleMethod(c, "t1"), "T", "f") - assertInvoke(getSingleMethod(c, "t2"), "C", "f") + assertInvoke(getMethod(c, "t1"), "T", "f") + assertInvoke(getMethod(c, "t2"), "C", "f") } @Test @@ -496,7 +496,7 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c, t) = compile(code) - assertNoInvoke(getSingleMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t1")) } @Test @@ -520,11 +520,11 @@ class InlinerTest extends BytecodeTesting { val List(c, oMirror, oModule, t) = compile(code, allowMessage = i => {count += 1; i.msg contains warn}) assert(count == 1, count) - assertNoInvoke(getSingleMethod(t, "f")) + assertNoInvoke(getMethod(t, "f")) - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) - assertInvoke(getSingleMethod(c, "t3"), "T", "f") + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) + assertInvoke(getMethod(c, "t3"), "T", "f") } @Test @@ -546,12 +546,12 @@ class InlinerTest extends BytecodeTesting { val List(assembly, c, t) = compile(code) - assertNoInvoke(getSingleMethod(t, "f")) + assertNoInvoke(getMethod(t, "f")) - assertNoInvoke(getSingleMethod(assembly, "n")) + assertNoInvoke(getMethod(assembly, "n")) - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) } @Test @@ -624,20 +624,20 @@ class InlinerTest extends BytecodeTesting { val List(ca, cb, t1, t2a, t2b) = compile(code, allowMessage = i => {count += 1; i.msg contains warning}) assert(count == 4, count) // see comments, f is not inlined 4 times - assertNoInvoke(getSingleMethod(t2a, "g2a")) - assertInvoke(getSingleMethod(t2b, "g2b"), "T1", "f") + assertNoInvoke(getMethod(t2a, "g2a")) + assertInvoke(getMethod(t2b, "g2b"), "T1", "f") - assertInvoke(getSingleMethod(ca, "m1a"), "T1", "f") - assertNoInvoke(getSingleMethod(ca, "m2a")) // no invoke, see comment on def g2a - assertNoInvoke(getSingleMethod(ca, "m3a")) - assertInvoke(getSingleMethod(ca, "m4a"), "T1", "f") - assertNoInvoke(getSingleMethod(ca, "m5a")) + assertInvoke(getMethod(ca, "m1a"), "T1", "f") + assertNoInvoke(getMethod(ca, "m2a")) // no invoke, see comment on def g2a + assertNoInvoke(getMethod(ca, "m3a")) + assertInvoke(getMethod(ca, "m4a"), "T1", "f") + assertNoInvoke(getMethod(ca, "m5a")) - assertInvoke(getSingleMethod(cb, "m1b"), "T1", "f") - assertInvoke(getSingleMethod(cb, "m2b"), "T1", "f") // invoke, see comment on def g2b - assertNoInvoke(getSingleMethod(cb, "m3b")) - assertInvoke(getSingleMethod(cb, "m4b"), "T1", "f") - assertNoInvoke(getSingleMethod(cb, "m5b")) + assertInvoke(getMethod(cb, "m1b"), "T1", "f") + assertInvoke(getMethod(cb, "m2b"), "T1", "f") // invoke, see comment on def g2b + assertNoInvoke(getMethod(cb, "m3b")) + assertInvoke(getMethod(cb, "m4b"), "T1", "f") + assertNoInvoke(getMethod(cb, "m5b")) } @Test @@ -654,7 +654,7 @@ class InlinerTest extends BytecodeTesting { |} // so d.f can be resolved statically. same for E.f """.stripMargin val List(c, d, e, eModule, t) = compile(code) - assertNoInvoke(getSingleMethod(t, "t1")) + assertNoInvoke(getMethod(t, "t1")) } @Test @@ -669,8 +669,8 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c, d, t) = compile(code) - assertNoInvoke(getSingleMethod(d, "m")) - assertNoInvoke(getSingleMethod(c, "m")) + assertNoInvoke(getMethod(d, "m")) + assertNoInvoke(getMethod(c, "m")) } @Test @@ -684,8 +684,8 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c, t) = compile(code) - val t1 = getSingleMethod(t, "t1") - val t2 = getSingleMethod(t, "t2") + val t1 = getMethod(t, "t1") + val t2 = getMethod(t, "t2") val cast = TypeOp(CHECKCAST, "C") Set(t1, t2).foreach(m => assert(m.instructions.contains(cast), m.instructions)) } @@ -765,27 +765,27 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c, t, u) = compile(code, allowMessage = _.msg contains "i()I is annotated @inline but cannot be inlined") - val m1 = getSingleMethod(c, "m1") + val m1 = getMethod(c, "m1") assertInvoke(m1, "T", "a") assertInvoke(m1, "T", "b") assertInvoke(m1, "T", "c") - assertNoInvoke(getSingleMethod(c, "m2")) + assertNoInvoke(getMethod(c, "m2")) - val m3 = getSingleMethod(c, "m3") + val m3 = getMethod(c, "m3") assertInvoke(m3, "T", "f") assertInvoke(m3, "T", "g") assertInvoke(m3, "T", "h") assertInvoke(m3, "T", "i") - val m4 = getSingleMethod(c, "m4") + val m4 = getMethod(c, "m4") assertInvoke(m4, "U", "a") assertInvoke(m4, "U", "b") assertInvoke(m4, "U", "c") - assertNoInvoke(getSingleMethod(c, "m5")) + assertNoInvoke(getMethod(c, "m5")) - val m6 = getSingleMethod(c, "m6") + val m6 = getMethod(c, "m6") assertInvoke(m6, "U", "f") assertInvoke(m6, "U", "g") assertInvoke(m6, "U", "h") @@ -869,15 +869,15 @@ class InlinerTest extends BytecodeTesting { val List(a, b, t) = compile(code, allowMessage = i => {c += 1; i.msg contains warn}) assert(c == 1, c) - assertInvoke(getSingleMethod(b, "t1"), "Aa", "f1") - assertInvoke(getSingleMethod(b, "t2"), "B", "B$$f2m") - assertInvoke(getSingleMethod(b, "t3"), "B", "") - assertInvoke(getSingleMethod(b, "t4"), "B", "") + assertInvoke(getMethod(b, "t1"), "Aa", "f1") + assertInvoke(getMethod(b, "t2"), "B", "B$$f2m") + assertInvoke(getMethod(b, "t3"), "B", "") + assertInvoke(getMethod(b, "t4"), "B", "") - assertInvoke(getSingleMethod(t, "t1"), "B", "f1") - assertInvoke(getSingleMethod(t, "t2"), "B", "B$$f2m") - assertInvoke(getSingleMethod(t, "t3"), "B", "") - assertInvoke(getSingleMethod(t, "t4"), "B", "") + assertInvoke(getMethod(t, "t1"), "B", "f1") + assertInvoke(getMethod(t, "t2"), "B", "B$$f2m") + assertInvoke(getMethod(t, "t3"), "B", "") + assertInvoke(getMethod(t, "t4"), "B", "") } @Test @@ -887,8 +887,8 @@ class InlinerTest extends BytecodeTesting { | def t = System.arraycopy(null, 0, null, 0, 0) |} """.stripMargin - val List(c) = newCompiler(extraArgs = compilerArgs + " -Yopt-inline-heuristics:everything").compileClasses(code) - assertInvoke(getSingleMethod(c, "t"), "java/lang/System", "arraycopy") + val c = newCompiler(extraArgs = compilerArgs + " -Yopt-inline-heuristics:everything").compileClass(code) + assertInvoke(getMethod(c, "t"), "java/lang/System", "arraycopy") } @Test @@ -902,7 +902,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - assertInvoke(getSingleMethod(c, "t"), "java/lang/Error", "") + assertInvoke(getMethod(c, "t"), "java/lang/Error", "") } @Test @@ -915,7 +915,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - val t = getSingleMethod(c, "t").instructions + val t = getInstructions(c, "t") assertNoInvoke(t) assert(1 == t.collect({case Ldc(_, "hai!") => }).size) // push-pop eliminates the first LDC("hai!") assert(1 == t.collect({case Jump(IFNONNULL, _) => }).size) // one single null check @@ -942,12 +942,12 @@ class InlinerTest extends BytecodeTesting { val List(c, _, _) = compile(code) - val t1 = getSingleMethod(c, "t1") + val t1 = getMethod(c, "t1") assertNoIndy(t1) // the indy call is inlined into t, and the closure elimination rewrites the closure invocation to the body method assertInvoke(t1, "C", "C$$$anonfun$2") - val t2 = getSingleMethod(c, "t2") + val t2 = getMethod(c, "t2") assertNoIndy(t2) assertInvoke(t2, "M$", "M$$$anonfun$1") } @@ -964,9 +964,9 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - val hMeth = findAsmMethod(c, "h") - val gMeth = findAsmMethod(c, "g") - val iMeth = findAsmMethod(c, "i") + val hMeth = getAsmMethod(c, "h") + val gMeth = getAsmMethod(c, "g") + val iMeth = getAsmMethod(c, "i") val fCall = getCallsite(gMeth, "f") val gCall = getCallsite(hMeth, "g") val hCall = getCallsite(iMeth, "h") @@ -993,7 +993,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(cl) = compile(code) - val List(b, c, d) = List("b", "c", "d").map(findAsmMethod(cl, _)) + val List(b, c, d) = List("b", "c", "d").map(getAsmMethod(cl, _)) val aCall = getCallsite(b, "a") val bCall = getCallsite(c, "b") val cCall = getCallsite(d, "c") @@ -1033,15 +1033,15 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - assertInvoke(getSingleMethod(c, "t1"), "C", "C$$$anonfun$1") - assertInvoke(getSingleMethod(c, "t2"), "C", "a") - assertInvoke(getSingleMethod(c, "t3"), "C", "b") - assertNoInvoke(getSingleMethod(c, "t4")) - assertNoInvoke(getSingleMethod(c, "t5")) - assertNoInvoke(getSingleMethod(c, "t6")) - assertInvoke(getSingleMethod(c, "t7"), "C", "c") - assertInvoke(getSingleMethod(c, "t8"), "scala/Predef$", "println") - assertNoInvoke(getSingleMethod(c, "t9")) + assertInvoke(getMethod(c, "t1"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "t2"), "C", "a") + assertInvoke(getMethod(c, "t3"), "C", "b") + assertNoInvoke(getMethod(c, "t4")) + assertNoInvoke(getMethod(c, "t5")) + assertNoInvoke(getMethod(c, "t6")) + assertInvoke(getMethod(c, "t7"), "C", "c") + assertInvoke(getMethod(c, "t8"), "scala/Predef$", "println") + assertNoInvoke(getMethod(c, "t9")) } @Test @@ -1066,15 +1066,15 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - assertNoInvoke(getSingleMethod(c, "t1")) - assertInvoke(getSingleMethod(c, "t2"), "C", "f2") - assertInvoke(getSingleMethod(c, "t3"), "C", "f1") - assertInvoke(getSingleMethod(c, "t4"), "C", "f2") - assertNoInvoke(getSingleMethod(c, "t5")) - assertInvoke(getSingleMethod(c, "t6"), "C", "f3") - assertNoInvoke(getSingleMethod(c, "t7")) - assertInvoke(getSingleMethod(c, "t8"), "C", "f1") - assertNoInvoke(getSingleMethod(c, "t9")) + assertNoInvoke(getMethod(c, "t1")) + assertInvoke(getMethod(c, "t2"), "C", "f2") + assertInvoke(getMethod(c, "t3"), "C", "f1") + assertInvoke(getMethod(c, "t4"), "C", "f2") + assertNoInvoke(getMethod(c, "t5")) + assertInvoke(getMethod(c, "t6"), "C", "f3") + assertNoInvoke(getMethod(c, "t7")) + assertInvoke(getMethod(c, "t8"), "C", "f1") + assertNoInvoke(getMethod(c, "t9")) } @Test @@ -1097,11 +1097,11 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - assertInvoke(getSingleMethod(c, "t1"), "C", "C$$$anonfun$1") - assertInvoke(getSingleMethod(c, "t2"), "C", "C$$$anonfun$2") - assertInvoke(getSingleMethod(c, "t3"), "scala/Function1", "apply$mcII$sp") - assertInvoke(getSingleMethod(c, "t4"), "scala/Function1", "apply$mcII$sp") - assertInvoke(getSingleMethod(c, "t5"), "C", "h") + assertInvoke(getMethod(c, "t1"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "t2"), "C", "C$$$anonfun$2") + assertInvoke(getMethod(c, "t3"), "scala/Function1", "apply$mcII$sp") + assertInvoke(getMethod(c, "t4"), "scala/Function1", "apply$mcII$sp") + assertInvoke(getMethod(c, "t5"), "C", "h") } @Test @@ -1121,7 +1121,7 @@ class InlinerTest extends BytecodeTesting { |when entering an exception handler declared in the inlined method.""".stripMargin val List(c) = compile(code, allowMessage = _.msg contains warn) - assertInvoke(getSingleMethod(c, "t"), "C", "g") + assertInvoke(getMethod(c, "t"), "C", "g") } @Test @@ -1145,8 +1145,8 @@ class InlinerTest extends BytecodeTesting { |that would cause an IllegalAccessError when inlined into class D.""".stripMargin val List(c, d) = compile(code, allowMessage = _.msg contains warn) - assertInvoke(getSingleMethod(c, "h"), "C", "f$1") - assertInvoke(getSingleMethod(d, "t"), "C", "h") + assertInvoke(getMethod(c, "h"), "C", "f$1") + assertInvoke(getMethod(d, "t"), "C", "h") } @Test @@ -1164,8 +1164,8 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c, d) = compile(code) - assertNoInvoke(getSingleMethod(c, "g")) - assertNoInvoke(getSingleMethod(d, "t")) + assertNoInvoke(getMethod(c, "g")) + assertNoInvoke(getMethod(d, "t")) } @Test @@ -1273,40 +1273,40 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c, _, _) = compile(code) - assertSameSummary(getSingleMethod(c, "t1"), List(BIPUSH, "C$$$anonfun$1", IRETURN)) - assertSameSummary(getSingleMethod(c, "t1a"), List(LCONST_1, "C$$$anonfun$2", IRETURN)) - assertSameSummary(getSingleMethod(c, "t2"), List(ICONST_1, ICONST_2, "C$$$anonfun$3",IRETURN)) + assertSameSummary(getMethod(c, "t1"), List(BIPUSH, "C$$$anonfun$1", IRETURN)) + assertSameSummary(getMethod(c, "t1a"), List(LCONST_1, "C$$$anonfun$2", IRETURN)) + assertSameSummary(getMethod(c, "t2"), List(ICONST_1, ICONST_2, "C$$$anonfun$3",IRETURN)) // val a = new ValKl(n); new ValKl(anonfun(a.x)).x // value class instantiation-extraction should be optimized by boxing elim - assertSameSummary(getSingleMethod(c, "t3"), List( + assertSameSummary(getMethod(c, "t3"), List( NEW, DUP, ICONST_1, "", ASTORE, NEW, DUP, ALOAD, "x", "C$$$anonfun$4", "", "x", IRETURN)) - assertSameSummary(getSingleMethod(c, "t4"), List(BIPUSH, "C$$$anonfun$5", "boxToInteger", ARETURN)) - assertSameSummary(getSingleMethod(c, "t4a"), List(ICONST_1, LDC, "C$$$anonfun$6", LRETURN)) - assertSameSummary(getSingleMethod(c, "t5"), List(BIPUSH, ICONST_3, "C$$$anonfun$7", "boxToInteger", ARETURN)) - assertSameSummary(getSingleMethod(c, "t5a"), List(BIPUSH, BIPUSH, I2B, "C$$$anonfun$8", IRETURN)) - assertSameSummary(getSingleMethod(c, "t6"), List(BIPUSH, "C$$$anonfun$9", RETURN)) - assertSameSummary(getSingleMethod(c, "t7"), List(ICONST_1, "C$$$anonfun$10", RETURN)) - assertSameSummary(getSingleMethod(c, "t8"), List(ICONST_1, LDC, "C$$$anonfun$11", LRETURN)) - assertSameSummary(getSingleMethod(c, "t9"), List(ICONST_1, "boxToInteger", "C$$$anonfun$12", RETURN)) + assertSameSummary(getMethod(c, "t4"), List(BIPUSH, "C$$$anonfun$5", "boxToInteger", ARETURN)) + assertSameSummary(getMethod(c, "t4a"), List(ICONST_1, LDC, "C$$$anonfun$6", LRETURN)) + assertSameSummary(getMethod(c, "t5"), List(BIPUSH, ICONST_3, "C$$$anonfun$7", "boxToInteger", ARETURN)) + assertSameSummary(getMethod(c, "t5a"), List(BIPUSH, BIPUSH, I2B, "C$$$anonfun$8", IRETURN)) + assertSameSummary(getMethod(c, "t6"), List(BIPUSH, "C$$$anonfun$9", RETURN)) + assertSameSummary(getMethod(c, "t7"), List(ICONST_1, "C$$$anonfun$10", RETURN)) + assertSameSummary(getMethod(c, "t8"), List(ICONST_1, LDC, "C$$$anonfun$11", LRETURN)) + assertSameSummary(getMethod(c, "t9"), List(ICONST_1, "boxToInteger", "C$$$anonfun$12", RETURN)) // t9a inlines Range.foreach, which is quite a bit of code, so just testing the core - assertInvoke(getSingleMethod(c, "t9a"), "C", "C$$$anonfun$13") - assertInvoke(getSingleMethod(c, "t9a"), "scala/runtime/BoxesRunTime", "boxToInteger") + assertInvoke(getMethod(c, "t9a"), "C", "C$$$anonfun$13") + assertInvoke(getMethod(c, "t9a"), "scala/runtime/BoxesRunTime", "boxToInteger") - assertSameSummary(getSingleMethod(c, "t10"), List( + assertSameSummary(getMethod(c, "t10"), List( ICONST_1, ISTORE, ALOAD, ILOAD, "C$$$anonfun$14", RETURN)) // t10a inlines Range.foreach - assertInvoke(getSingleMethod(c, "t10a"), "C", "C$$$anonfun$15") - assertDoesNotInvoke(getSingleMethod(c, "t10a"), "boxToInteger") + assertInvoke(getMethod(c, "t10a"), "C", "C$$$anonfun$15") + assertDoesNotInvoke(getMethod(c, "t10a"), "boxToInteger") } @Test @@ -1329,8 +1329,8 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c) = compile(code) - assertSameCode(getSingleMethod(c, "t1"), List(Op(ICONST_0), Op(ICONST_1), Op(IADD), Op(IRETURN))) - assertEquals(getSingleMethod(c, "t2").instructions collect { case i: Invoke => i.owner +"."+ i.name }, List( + assertSameCode(getMethod(c, "t1"), List(Op(ICONST_0), Op(ICONST_1), Op(IADD), Op(IRETURN))) + assertEquals(getInstructions(c, "t2") collect { case i: Invoke => i.owner +"."+ i.name }, List( "scala/runtime/IntRef.create", "C.C$$$anonfun$1")) } @@ -1370,11 +1370,11 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c) = compile(code) - assertSameCode(getSingleMethod(c, "t1"), List(Op(ICONST_3), Op(ICONST_4), Op(IADD), Op(IRETURN))) - assertSameCode(getSingleMethod(c, "t2"), List(Op(ICONST_1), Op(ICONST_2), Op(IADD), Op(IRETURN))) - assertSameCode(getSingleMethod(c, "t3"), List(Op(ICONST_1), Op(ICONST_3), Op(ISUB), Op(IRETURN))) - assertNoInvoke(getSingleMethod(c, "t4")) - assertNoInvoke(getSingleMethod(c, "t5")) + assertSameCode(getMethod(c, "t1"), List(Op(ICONST_3), Op(ICONST_4), Op(IADD), Op(IRETURN))) + assertSameCode(getMethod(c, "t2"), List(Op(ICONST_1), Op(ICONST_2), Op(IADD), Op(IRETURN))) + assertSameCode(getMethod(c, "t3"), List(Op(ICONST_1), Op(ICONST_3), Op(ISUB), Op(IRETURN))) + assertNoInvoke(getMethod(c, "t4")) + assertNoInvoke(getMethod(c, "t5")) } @Test @@ -1400,10 +1400,10 @@ class InlinerTest extends BytecodeTesting { |class D extends C """.stripMargin val List(c, _) = compile(code) - def casts(m: String) = getSingleMethod(c, m).instructions collect { case TypeOp(CHECKCAST, tp) => tp } - assertSameCode(getSingleMethod(c, "t1"), List(VarOp(ALOAD, 1), Op(ARETURN))) - assertSameCode(getSingleMethod(c, "t2"), List(VarOp(ALOAD, 1), Op(ARETURN))) - assertSameCode(getSingleMethod(c, "t3"), List(VarOp(ALOAD, 1), TypeOp(CHECKCAST, "C"), Op(ARETURN))) + def casts(m: String) = getInstructions(c, m) collect { case TypeOp(CHECKCAST, tp) => tp } + assertSameCode(getMethod(c, "t1"), List(VarOp(ALOAD, 1), Op(ARETURN))) + assertSameCode(getMethod(c, "t2"), List(VarOp(ALOAD, 1), Op(ARETURN))) + assertSameCode(getMethod(c, "t3"), List(VarOp(ALOAD, 1), TypeOp(CHECKCAST, "C"), Op(ARETURN))) assertEquals(casts("t4"), List("C")) assertEquals(casts("t5"), Nil) assertEquals(casts("t6"), Nil) @@ -1428,8 +1428,8 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val cls = compile(code) - val test = cls.find(_.name == "Test$").get - assertSameSummary(getSingleMethod(test, "f"), List( + val test = findClass(cls, "Test$") + assertSameSummary(getMethod(test, "f"), List( GETSTATIC, "mkFoo", BIPUSH, ISTORE, IFNONNULL, ACONST_NULL, ATHROW, -1 /*label*/, @@ -1448,7 +1448,7 @@ class InlinerTest extends BytecodeTesting { val List(c) = compile(code) // box-unbox will clean it up - assertSameSummary(getSingleMethod(c, "t"), List( + assertSameSummary(getMethod(c, "t"), List( ALOAD, "C$$$anonfun$1", IFEQ /*A*/, "C$$$anonfun$2", IRETURN, -1 /*A*/, "C$$$anonfun$3", IRETURN)) @@ -1460,7 +1460,7 @@ class InlinerTest extends BytecodeTesting { val codeB = "class B { def t(a: A) = a.f }" // tests that no warning is emitted val List(a, b) = compileClassesSeparately(List(codeA, codeB), extraArgs = "-Yopt:l:project -Yopt-warnings") - assertInvoke(getSingleMethod(b, "t"), "A", "f") + assertInvoke(getMethod(b, "t"), "A", "f") } @Test @@ -1472,7 +1472,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c, t1, t2) = compile(code, allowMessage = _ => true) // the forwarder C.f is inlined, so there's no invocation - assertSameSummary(getSingleMethod(c, "f"), List(ICONST_1, IRETURN)) + assertSameSummary(getMethod(c, "f"), List(ICONST_1, IRETURN)) } @Test @@ -1485,7 +1485,7 @@ class InlinerTest extends BytecodeTesting { |class C { def t = (new K).f } """.stripMargin val c :: _ = compile(code) - assertSameSummary(getSingleMethod(c, "t"), List(NEW, "", ICONST_1, IRETURN)) // ICONST_1, U.f is inlined (not T.f) + assertSameSummary(getMethod(c, "t"), List(NEW, "", ICONST_1, IRETURN)) // ICONST_1, U.f is inlined (not T.f) } @Test @@ -1497,7 +1497,7 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c) = compile(code) - val t = getSingleMethod(c, "t") + val t = getMethod(c, "t") assertNoIndy(t) assertInvoke(t, "C", "C$$$anonfun$1") } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 3867f101451d..fa76c0d93086 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -22,20 +22,20 @@ class MethodLevelOptsTest extends BytecodeTesting { def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1)) - def locals(c: ClassNode, m: String) = findAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2) + def locals(c: ClassNode, m: String) = getAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2) @Test def eliminateEmptyTry(): Unit = { val code = "def f = { try {} catch { case _: Throwable => 0; () }; 1 }" val warn = "a pure expression does nothing in statement position" - assertSameCode(singleMethodInstructions(code, allowMessage = _.msg contains warn), wrapInDefault(Op(ICONST_1), Op(IRETURN))) + assertSameCode(compileInstructions(code, allowMessage = _.msg contains warn), wrapInDefault(Op(ICONST_1), Op(IRETURN))) } @Test def eliminateLoadBoxedUnit(): Unit = { // the compiler inserts a boxed into the try block. it's therefore non-empty (and live) and not eliminated. val code = "def f = { try {} catch { case _: Throwable => 0 }; 1 }" - val m = singleMethod(code) + val m = compileMethod(code) assertTrue(m.handlers.length == 0) assertSameCode(m, List(Op(ICONST_1), Op(IRETURN))) } @@ -44,7 +44,7 @@ class MethodLevelOptsTest extends BytecodeTesting { def inlineThrowInCatchNotTry(): Unit = { // the try block does not contain the `ATHROW` instruction, but in the catch block, `ATHROW` is inlined val code = "def f(e: Exception) = throw { try e catch { case _: Throwable => e } }" - val m = singleMethod(code) + val m = compileMethod(code) assertHandlerLabelPostions(m.handlers.head, m.instructions, 0, 3, 5) assertSameCode(m.instructions, wrapInDefault(VarOp(ALOAD, 1), Label(3), Op(ATHROW), Label(5), FrameEntry(4, List(), List("java/lang/Throwable")), Op(POP), VarOp(ALOAD, 1), Op(ATHROW)) @@ -55,7 +55,7 @@ class MethodLevelOptsTest extends BytecodeTesting { def inlineReturnInCatchNotTry(): Unit = { val code = "def f: Int = return { try 1 catch { case _: Throwable => 2 } }" // cannot inline the IRETURN into the try block (because RETURN may throw IllegalMonitorState) - val m = singleMethod(code) + val m = compileMethod(code) assertHandlerLabelPostions(m.handlers.head, m.instructions, 0, 3, 5) assertSameCode(m.instructions, wrapInDefault(Op(ICONST_1), Label(3), Op(IRETURN), Label(5), FrameEntry(4, List(), List("java/lang/Throwable")), Op(POP), Op(ICONST_2), Op(IRETURN))) @@ -77,7 +77,7 @@ class MethodLevelOptsTest extends BytecodeTesting { | println(x) | } """.stripMargin - val m = singleMethod(code) + val m = compileMethod(code) assertTrue(m.handlers.isEmpty) assertSameCode(m, List(Op(ICONST_3), Op(IRETURN))) } @@ -97,8 +97,8 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameCode(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List( Op(ACONST_NULL), Invoke(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false), Op(ARETURN))) } @@ -114,9 +114,9 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) assertSameCode( - getSingleMethod(c, "t"), List(Ldc(LDC, "c"), Op(ARETURN))) + getMethod(c, "t"), List(Ldc(LDC, "c"), Op(ARETURN))) } @Test @@ -134,9 +134,9 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) - assertSameCode(getSingleMethod(c, "t"), List( + assertSameCode(getMethod(c, "t"), List( Ldc(LDC, "el"), VarOp(ASTORE, 1), Field(GETSTATIC, "scala/Predef$", "MODULE$", "Lscala/Predef$;"), VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), Op(ACONST_NULL), VarOp(ASTORE, 1), @@ -158,8 +158,8 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameCode(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List( IntOp(BIPUSH, 23), IntOp(NEWARRAY, 5), Op(POP), VarOp(ILOAD, 1), VarOp(ILOAD, 2), Op(IADD), Op(IRETURN))) } @@ -173,8 +173,8 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameCode(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List( TypeOp(NEW, "java/lang/Integer"), Ldc(LDC, "nono"), Invoke(INVOKESPECIAL, "java/lang/Integer", "", "(Ljava/lang/String;)V", false), VarOp(ILOAD, 1), VarOp(ILOAD, 2), Op(IADD), Op(IRETURN))) } @@ -199,8 +199,8 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameCode(getSingleMethod(c, "t"), List(Op(ICONST_0), Op(IRETURN))) + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List(Op(ICONST_0), Op(IRETURN))) } @Test @@ -215,8 +215,8 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameCode(getSingleMethod(c, "t"), List( + val c = compileClass(code) + assertSameCode(getMethod(c, "t"), List( IntOp(BIPUSH, 30), VarOp(ISTORE, 3), // no constant propagation, so we keep the store (and load below) of a const VarOp(ILOAD, 1), VarOp(ILOAD, 2), @@ -236,8 +236,8 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - val t = getSingleMethod(c, "t") + val c = compileClass(code) + val t = getMethod(c, "t") assert(!t.instructions.exists(_.opcode == INVOKEDYNAMIC), t) } @@ -317,23 +317,23 @@ class MethodLevelOptsTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) - - assertNoInvoke(getSingleMethod(c, "t1")) - assertNoInvoke(getSingleMethod(c, "t2")) - assertInvoke(getSingleMethod(c, "t3"), "scala/runtime/BoxesRunTime", "unboxToInt") - assertInvoke(getSingleMethod(c, "t4"), "scala/runtime/BoxesRunTime", "boxToLong") - assertNoInvoke(getSingleMethod(c, "t5")) - assertNoInvoke(getSingleMethod(c, "t6")) - assertNoInvoke(getSingleMethod(c, "t7")) - assertSameSummary(getSingleMethod(c, "t8"), List(ICONST_0, IRETURN)) - assertNoInvoke(getSingleMethod(c, "t9")) + val c = compileClass(code) + + assertNoInvoke(getMethod(c, "t1")) + assertNoInvoke(getMethod(c, "t2")) + assertInvoke(getMethod(c, "t3"), "scala/runtime/BoxesRunTime", "unboxToInt") + assertInvoke(getMethod(c, "t4"), "scala/runtime/BoxesRunTime", "boxToLong") + assertNoInvoke(getMethod(c, "t5")) + assertNoInvoke(getMethod(c, "t6")) + assertNoInvoke(getMethod(c, "t7")) + assertSameSummary(getMethod(c, "t8"), List(ICONST_0, IRETURN)) + assertNoInvoke(getMethod(c, "t9")) // t10: no invocation of unbox - assertEquals(getSingleMethod(c, "t10").instructions collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( + assertEquals(getInstructions(c, "t10") collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( ("java/lang/Integer", "valueOf"), ("C", "escape"))) - assertSameSummary(getSingleMethod(c, "t11"), List( + assertSameSummary(getMethod(c, "t11"), List( BIPUSH, "valueOf", ASTORE /*2*/, BIPUSH, "valueOf", ASTORE /*3*/, ALOAD /*0*/, ALOAD /*2*/, "escape", @@ -341,7 +341,7 @@ class MethodLevelOptsTest extends BytecodeTesting { ASTORE /*4*/, GETSTATIC /*Predef*/, ALOAD /*4*/, "Integer2int", IRETURN)) // no unbox invocations - assertEquals(getSingleMethod(c, "t12").instructions collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( + assertEquals(getInstructions(c, "t12") collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( ("java/lang/Integer", "valueOf"), ("java/lang/Integer", "valueOf"), ("C", "escape"))) @@ -393,14 +393,14 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameSummary(getSingleMethod(c, "t1"), List(ICONST_0, IRETURN)) - assertNoInvoke(getSingleMethod(c, "t2")) - assertSameSummary(getSingleMethod(c, "t3"), List(LDC, LDC, LADD, LRETURN)) - assertNoInvoke(getSingleMethod(c, "t4")) - assertEquals(getSingleMethod(c, "t5").instructions collect { case Field(_, owner, name, _) => s"$owner.$name" }, + val c = compileClass(code) + assertSameSummary(getMethod(c, "t1"), List(ICONST_0, IRETURN)) + assertNoInvoke(getMethod(c, "t2")) + assertSameSummary(getMethod(c, "t3"), List(LDC, LDC, LADD, LRETURN)) + assertNoInvoke(getMethod(c, "t4")) + assertEquals(getInstructions(c, "t5") collect { case Field(_, owner, name, _) => s"$owner.$name" }, List("scala/runtime/IntRef.elem")) - assertEquals(getSingleMethod(c, "t6").instructions collect { case Field(op, owner, name, _) => s"$op $owner.$name" }, + assertEquals(getInstructions(c, "t6") collect { case Field(op, owner, name, _) => s"$op $owner.$name" }, List(s"$PUTFIELD scala/runtime/IntRef.elem", s"$GETFIELD scala/runtime/IntRef.elem")) } @@ -457,23 +457,23 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertNoInvoke(getSingleMethod(c, "t1")) - assertSameSummary(getSingleMethod(c, "t2"), List(ICONST_1, ICONST_3, IADD, IRETURN)) - assertSameSummary(getSingleMethod(c, "t3"), List(ICONST_3, ICONST_4, IADD, IRETURN)) - assertSameSummary(getSingleMethod(c, "t4"), List(ICONST_3, "boxToInteger", ARETURN)) - assertEquals(getSingleMethod(c, "t5").instructions collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( + val c = compileClass(code) + assertNoInvoke(getMethod(c, "t1")) + assertSameSummary(getMethod(c, "t2"), List(ICONST_1, ICONST_3, IADD, IRETURN)) + assertSameSummary(getMethod(c, "t3"), List(ICONST_3, ICONST_4, IADD, IRETURN)) + assertSameSummary(getMethod(c, "t4"), List(ICONST_3, "boxToInteger", ARETURN)) + assertEquals(getInstructions(c, "t5") collect { case Invoke(_, owner, name, _, _) => (owner, name) }, List( ("scala/runtime/BoxesRunTime", "boxToInteger"), ("scala/runtime/BoxesRunTime", "boxToInteger"), ("C", "tpl"), ("scala/Tuple2", "_1$mcI$sp"))) - assertSameSummary(getSingleMethod(c, "t6"), List(ICONST_1, ICONST_2, ISUB, IRETURN)) - assertSameSummary(getSingleMethod(c, "t7"), List( + assertSameSummary(getMethod(c, "t6"), List(ICONST_1, ICONST_2, ISUB, IRETURN)) + assertSameSummary(getMethod(c, "t7"), List( ICONST_1, ICONST_2, ISTORE, ISTORE, ICONST_3, ISTORE, ILOAD, ILOAD, IADD, ILOAD, IADD, IRETURN)) - assertNoInvoke(getSingleMethod(c, "t8")) - assertNoInvoke(getSingleMethod(c, "t9")) + assertNoInvoke(getMethod(c, "t8")) + assertNoInvoke(getMethod(c, "t9")) } @Test @@ -522,14 +522,14 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertSameSummary(getSingleMethod(c, "t1"), List(NEW, DUP, "", ARETURN)) - assertSameCode(getSingleMethod(c, "t2"), List(Op(LCONST_0), Op(LRETURN))) - assertSameCode(getSingleMethod(c, "t3"), List(Op(ICONST_1), Op(IRETURN))) - assertSameCode(getSingleMethod(c, "t4"), List(Op(ICONST_1), Op(IRETURN))) - assertSameCode(getSingleMethod(c, "t5"), List(Op(DCONST_0), Op(DRETURN))) - assertSameCode(getSingleMethod(c, "t6"), List(Op(ACONST_NULL), Op(ARETURN))) - assertSameCode(getSingleMethod(c, "t7"), List(Op(ICONST_0), Op(IRETURN))) + val c = compileClass(code) + assertSameSummary(getMethod(c, "t1"), List(NEW, DUP, "", ARETURN)) + assertSameCode(getMethod(c, "t2"), List(Op(LCONST_0), Op(LRETURN))) + assertSameCode(getMethod(c, "t3"), List(Op(ICONST_1), Op(IRETURN))) + assertSameCode(getMethod(c, "t4"), List(Op(ICONST_1), Op(IRETURN))) + assertSameCode(getMethod(c, "t5"), List(Op(DCONST_0), Op(DRETURN))) + assertSameCode(getMethod(c, "t6"), List(Op(ACONST_NULL), Op(ARETURN))) + assertSameCode(getMethod(c, "t7"), List(Op(ICONST_0), Op(IRETURN))) } @Test @@ -542,9 +542,9 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) assertSameCode( - getSingleMethod(c, "t"), List( + getMethod(c, "t"), List( VarOp(ALOAD, 1), Jump(IFNULL, Label(6)), Op(ICONST_1), Op(IRETURN), Label(6), Op(ICONST_0), Op(IRETURN))) } @@ -613,28 +613,28 @@ class MethodLevelOptsTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) - def stores(m: String) = getSingleMethod(c, m).instructions.filter(_.opcode == ASTORE) + val c = compileClass(code) + def stores(m: String) = getInstructions(c, m).filter(_.opcode == ASTORE) assertEquals(locals(c, "t1"), List(("this",0), ("kept1",1), ("result",2))) assert(stores("t1") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t1"))) + textify(getAsmMethod(c, "t1"))) assertEquals(locals(c, "t2"), List(("this",0), ("kept2",1), ("kept3",2))) assert(stores("t2") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t2"))) + textify(getAsmMethod(c, "t2"))) assertEquals(locals(c, "t3"), List(("this",0), ("kept4",1))) assert(stores("t3") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t3"))) + textify(getAsmMethod(c, "t3"))) assertEquals(locals(c, "t4"), List(("this",0), ("kept5",1))) assert(stores("t4") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t4"))) + textify(getAsmMethod(c, "t4"))) assertEquals(locals(c, "t5"), List(("this",0), ("kept6",1))) assert(stores("t5") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), - textify(findAsmMethod(c, "t5"))) + textify(getAsmMethod(c, "t5"))) } @Test @@ -681,13 +681,13 @@ class MethodLevelOptsTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) assertEquals(locals(c, "t1"), List(("this", 0), ("x", 1))) assertEquals(locals(c, "t2"), List(("this", 0), ("x", 1))) // we don't have constant propagation (yet). // the local var can't be optimized as a store;laod sequence, there's a GETSTATIC between the two - assertSameSummary(getSingleMethod(c, "t2"), List( + assertSameSummary(getMethod(c, "t2"), List( ICONST_2, ISTORE, GETSTATIC, ILOAD, "boxToInteger", "println", RETURN)) assertEquals(locals(c, "t3"), List(("this", 0))) @@ -709,8 +709,8 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - val t = getSingleMethod(c, "t") + val c = compileClass(code) + val t = getMethod(c, "t") assertEquals(t.handlers, Nil) assertEquals(locals(c, "t"), List(("this", 0))) assertSameSummary(t, List(GETSTATIC, LDC, "print", -1, GOTO)) @@ -727,8 +727,8 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) - assertNoInvoke(getSingleMethod(c, "compare")) + val c = compileClass(code) + assertNoInvoke(getMethod(c, "compare")) } @Test @@ -741,9 +741,9 @@ class MethodLevelOptsTest extends BytecodeTesting { | } |} """.stripMargin - val List(c) = compileClasses(code) + val c = compileClass(code) - assertSameSummary(getSingleMethod(c, "t"), List( + assertSameSummary(getMethod(c, "t"), List( BIPUSH, ILOAD, IF_ICMPNE, BIPUSH, ILOAD, IF_ICMPNE, LDC, ASTORE, GOTO, diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala index 99a662b8977a..63bbcc396bb6 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala @@ -110,10 +110,10 @@ class UnreachableCodeTest extends ClearAfterClass { @Test def basicEliminationCompiler(): Unit = { val code = "def f: Int = { return 1; 2 }" - val withDce = dceCompiler.singleMethodInstructions(code) + val withDce = dceCompiler.compileInstructions(code) assertSameCode(withDce.dropNonOp, List(Op(ICONST_1), Op(IRETURN))) - val noDce = noOptCompiler.singleMethodInstructions(code) + val noDce = noOptCompiler.compileInstructions(code) // The emitted code is ICONST_1, IRETURN, ICONST_2, IRETURN. The latter two are dead. // @@ -139,23 +139,23 @@ class UnreachableCodeTest extends ClearAfterClass { def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1)) val code = "def f: Int = { return 0; try { 1 } catch { case _: Exception => 2 } }" - val m = dceCompiler.singleMethod(code) + val m = dceCompiler.compileMethod(code) assertTrue(m.handlers.isEmpty) // redundant (if code is gone, handler is gone), but done once here for extra safety assertSameCode(m.instructions, wrapInDefault(Op(ICONST_0), Op(IRETURN))) val code2 = "def f: Unit = { try { } catch { case _: Exception => () }; () }" // requires fixpoint optimization of methodOptCompiler (dce alone is not enough): first the handler is eliminated, then it's dead catch block. - assertSameCode(methodOptCompiler.singleMethodInstructions(code2), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.compileInstructions(code2), wrapInDefault(Op(RETURN))) val code3 = "def f: Unit = { try { } catch { case _: Exception => try { } catch { case _: Exception => () } }; () }" - assertSameCode(methodOptCompiler.singleMethodInstructions(code3), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.compileInstructions(code3), wrapInDefault(Op(RETURN))) // this example requires two iterations to get rid of the outer handler. // the first iteration of DCE cannot remove the inner handler. then the inner (empty) handler is removed. // then the second iteration of DCE removes the inner catch block, and then the outer handler is removed. val code4 = "def f: Unit = { try { try { } catch { case _: Exception => () } } catch { case _: Exception => () }; () }" - assertSameCode(methodOptCompiler.singleMethodInstructions(code4), wrapInDefault(Op(RETURN))) + assertSameCode(methodOptCompiler.compileInstructions(code4), wrapInDefault(Op(RETURN))) } @Test // test the dce-testing tools @@ -214,35 +214,35 @@ class UnreachableCodeTest extends ClearAfterClass { | def t4 = cons(nt) |} """.stripMargin - val List(c) = noOptCompiler.compileClasses(code) + val c = noOptCompiler.compileClass(code) - assertSameSummary(getSingleMethod(c, "nl"), List(ACONST_NULL, ARETURN)) + assertSameSummary(getMethod(c, "nl"), List(ACONST_NULL, ARETURN)) - assertSameSummary(getSingleMethod(c, "nt"), List( + assertSameSummary(getMethod(c, "nt"), List( NEW, DUP, LDC, "", ATHROW)) - assertSameSummary(getSingleMethod(c, "t1"), List( + assertSameSummary(getMethod(c, "t1"), List( ALOAD, ACONST_NULL, "cons", RETURN)) // GenBCode introduces POP; ACONST_NULL after loading an expression of type scala.runtime.Null$, // see comment in BCodeBodyBuilder.adapt - assertSameSummary(getSingleMethod(c, "t2"), List( + assertSameSummary(getMethod(c, "t2"), List( ALOAD, ALOAD, "nl", POP, ACONST_NULL, "cons", RETURN)) // the bytecode generated by GenBCode is ... ATHROW; INVOKEVIRTUAL C.cons; RETURN // the ASM classfile writer creates a new basic block (creates a label) right after the ATHROW // and replaces all instructions by NOP*; ATHROW, see comment in BCodeBodyBuilder.adapt // NOTE: DCE is enabled by default and gets rid of the redundant code (tested below) - assertSameSummary(getSingleMethod(c, "t3"), List( + assertSameSummary(getMethod(c, "t3"), List( ALOAD, NEW, DUP, LDC, "", ATHROW, NOP, NOP, NOP, ATHROW)) // GenBCode introduces an ATHROW after the invocation of C.nt, see BCodeBodyBuilder.adapt // NOTE: DCE is enabled by default and gets rid of the redundant code (tested below) - assertSameSummary(getSingleMethod(c, "t4"), List( + assertSameSummary(getMethod(c, "t4"), List( ALOAD, ALOAD, "nt", ATHROW, NOP, NOP, NOP, ATHROW)) - val List(cDCE) = dceCompiler.compileClasses(code) - assertSameSummary(getSingleMethod(cDCE, "t3"), List(ALOAD, NEW, DUP, LDC, "", ATHROW)) - assertSameSummary(getSingleMethod(cDCE, "t4"), List(ALOAD, ALOAD, "nt", ATHROW)) + val cDCE = dceCompiler.compileClass(code) + assertSameSummary(getMethod(cDCE, "t3"), List(ALOAD, NEW, DUP, LDC, "", ATHROW)) + assertSameSummary(getMethod(cDCE, "t4"), List(ALOAD, ALOAD, "nt", ATHROW)) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala index 303600aa70fd..c9c98b403b56 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala @@ -8,9 +8,9 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import scala.collection.JavaConverters._ -import scala.tools.partest.ASMConverters import scala.tools.partest.ASMConverters._ import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class UnusedLocalVariablesTest extends BytecodeTesting { @@ -48,7 +48,7 @@ class UnusedLocalVariablesTest extends BytecodeTesting { | } |} |""".stripMargin - val cls = compileClasses(code).head + val cls = compileClass(code) val m = convertMethod(cls.methods.asScala.toList.find(_.desc == "(I)V").get) assertTrue(m.localVars.length == 2) // this, a, but not y @@ -69,19 +69,14 @@ class UnusedLocalVariablesTest extends BytecodeTesting { |} """.stripMargin - val clss2 = compileClasses(code2) - val cls2 = clss2.find(_.name == "C").get - val companion2 = clss2.find(_.name == "C$").get + val List(cls2, companion2) = compileClasses(code2) - val clsConstr = convertMethod(cls2.methods.asScala.toList.find(_.name == "").get) - val companionConstr = convertMethod(companion2.methods.asScala.toList.find(_.name == "").get) - - assertTrue(clsConstr.localVars.length == 1) // this - assertTrue(companionConstr.localVars.length == 1) // this + assertTrue(getMethod(cls2, "").localVars.length == 1) // this + assertTrue(getMethod(companion2, "").localVars.length == 1) // this } def assertLocalVarCount(code: String, numVars: Int): Unit = { - assertTrue(singleMethod(code).localVars.length == numVars) + assertTrue(compileMethod(code).localVars.length == numVars) } } diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index cc6d1d748356..b6e8d4fbf2d7 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -38,9 +38,9 @@ class PatmatBytecodeTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) - assert(getSingleMethod(c, "s1").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) - assert(getSingleMethod(c, "s2").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) + val c = compileClass(code) + assert(getInstructions(c, "s1").count(_.opcode == TABLESWITCH) == 1, textify(c)) + assert(getInstructions(c, "s2").count(_.opcode == TABLESWITCH) == 1, textify(c)) } @Test @@ -66,9 +66,9 @@ class PatmatBytecodeTest extends BytecodeTesting { |} """.stripMargin - val List(c) = compileClasses(code) - assert(getSingleMethod(c, "s1").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) - assert(getSingleMethod(c, "s2").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) + val c = compileClass(code) + assert(getInstructions(c, "s1").count(_.opcode == TABLESWITCH) == 1, textify(c)) + assert(getInstructions(c, "s2").count(_.opcode == TABLESWITCH) == 1, textify(c)) } @Test @@ -81,9 +81,9 @@ class PatmatBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - val c = optCompiler.compileClasses(code).head + val c :: _ = optCompiler.compileClasses(code) - assertSameSummary(getSingleMethod(c, "a"), List( + assertSameSummary(getMethod(c, "a"), List( NEW, DUP, ICONST_1, LDC, "", "y", ARETURN)) } @@ -98,8 +98,8 @@ class PatmatBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - val c = optCompiler.compileClasses(code).head - assert(!getSingleMethod(c, "a").instructions.exists(i => i.opcode == IFNULL || i.opcode == IFNONNULL), textify(findAsmMethod(c, "a"))) + val c :: _ = optCompiler.compileClasses(code) + assert(!getInstructions(c, "a").exists(i => i.opcode == IFNULL || i.opcode == IFNONNULL), textify(getAsmMethod(c, "a"))) } @Test @@ -112,8 +112,8 @@ class PatmatBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - val c = optCompiler.compileClasses(code).head - assertSameSummary(getSingleMethod(c, "a"), List( + val c :: _ = optCompiler.compileClasses(code) + assertSameSummary(getMethod(c, "a"), List( NEW, DUP, ICONST_1, "boxToInteger", LDC, "", ASTORE /*1*/, ALOAD /*1*/, "y", ASTORE /*2*/, ALOAD /*1*/, "x", INSTANCEOF, IFNE /*R*/, @@ -133,7 +133,7 @@ class PatmatBytecodeTest extends BytecodeTesting { | } |} """.stripMargin - val c = optCompiler.compileClasses(code, allowMessage = _.msg.contains("may not be exhaustive")).head + val c = optCompiler.compileClass(code, allowMessage = _.msg.contains("may not be exhaustive")) val expected = List( ALOAD /*1*/ , INSTANCEOF /*::*/ , IFEQ /*A*/ , @@ -142,8 +142,8 @@ class PatmatBytecodeTest extends BytecodeTesting { -1 /*A*/ , NEW /*MatchError*/ , DUP, ALOAD /*1*/ , "", ATHROW, -1 /*B*/ , ILOAD, IRETURN) - assertSameSummary(getSingleMethod(c, "a"), expected) - assertSameSummary(getSingleMethod(c, "b"), expected) + assertSameSummary(getMethod(c, "a"), expected) + assertSameSummary(getMethod(c, "b"), expected) } @Test @@ -166,17 +166,17 @@ class PatmatBytecodeTest extends BytecodeTesting { |} """.stripMargin val List(c, cMod) = optCompiler.compileClasses(code) - assertSameSummary(getSingleMethod(c, "t1"), List(ICONST_1, ICONST_2, IADD, IRETURN)) - assertSameSummary(getSingleMethod(c, "t2"), List(ICONST_1, IRETURN)) - assertInvokedMethods(getSingleMethod(c, "t3"), List("C.tplCall", "scala/Tuple2._1", "scala/Tuple2._2$mcI$sp", "scala/MatchError.", "java/lang/String.length")) - assertInvokedMethods(getSingleMethod(c, "t4"), List("C.tplCall", "scala/Tuple2._2$mcI$sp", "scala/MatchError.")) - assertNoInvoke(getSingleMethod(c, "t5")) - assertSameSummary(getSingleMethod(c, "t6"), List(BIPUSH, IRETURN)) + assertSameSummary(getMethod(c, "t1"), List(ICONST_1, ICONST_2, IADD, IRETURN)) + assertSameSummary(getMethod(c, "t2"), List(ICONST_1, IRETURN)) + assertInvokedMethods(getMethod(c, "t3"), List("C.tplCall", "scala/Tuple2._1", "scala/Tuple2._2$mcI$sp", "scala/MatchError.", "java/lang/String.length")) + assertInvokedMethods(getMethod(c, "t4"), List("C.tplCall", "scala/Tuple2._2$mcI$sp", "scala/MatchError.")) + assertNoInvoke(getMethod(c, "t5")) + assertSameSummary(getMethod(c, "t6"), List(BIPUSH, IRETURN)) // MatchError reachable because of the type pattern `s: String` - assertInvokedMethods(getSingleMethod(c, "t7"), List("C.a", "C.b", "scala/MatchError.", "java/lang/String.length")) - assertSameSummary(getSingleMethod(c, "t8"), List(ALOAD, "b", IRETURN)) + assertInvokedMethods(getMethod(c, "t7"), List("C.a", "C.b", "scala/MatchError.", "java/lang/String.length")) + assertSameSummary(getMethod(c, "t8"), List(ALOAD, "b", IRETURN)) // C allocation not eliminated - constructor may have side-effects. - assertSameSummary(getSingleMethod(c, "t9"), List(NEW, DUP, LDC, BIPUSH, "", "a", "toString", ARETURN)) + assertSameSummary(getMethod(c, "t9"), List(NEW, DUP, LDC, BIPUSH, "", "a", "toString", ARETURN)) } } diff --git a/test/junit/scala/tools/testing/BytecodeTesting.scala b/test/junit/scala/tools/testing/BytecodeTesting.scala index d6f8dbc21937..b11ad271483d 100644 --- a/test/junit/scala/tools/testing/BytecodeTesting.scala +++ b/test/junit/scala/tools/testing/BytecodeTesting.scala @@ -44,14 +44,23 @@ class Compiler(val global: Global) { } } - def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[(String, Array[Byte])] = { + def compileToBytes(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[(String, Array[Byte])] = { val run = newRun run.compileSources(makeSourceFile(scalaCode, "unitTestSource.scala") :: javaCode.map(p => makeSourceFile(p._1, p._2))) checkReport(allowMessage) getGeneratedClassfiles(global.settings.outputDirs.getSingleOutput.get) } - def compileTransformed(scalaCode: String, javaCode: List[(String, String)] = Nil, beforeBackend: global.Tree => global.Tree): List[(String, Array[Byte])] = { + def compileClasses(code: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { + readAsmClasses(compileToBytes(code, javaCode, allowMessage)) + } + + def compileClass(code: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): ClassNode = { + val List(c) = compileClasses(code, javaCode, allowMessage) + c + } + + def compileToBytesTransformed(scalaCode: String, javaCode: List[(String, String)] = Nil, beforeBackend: global.Tree => global.Tree): List[(String, Array[Byte])] = { import global._ settings.stopBefore.value = "jvm" :: Nil val run = newRun @@ -68,22 +77,30 @@ class Compiler(val global: Global) { getGeneratedClassfiles(settings.outputDirs.getSingleOutput.get) } - def compileClasses(code: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] = { - readAsmClasses(compile(code, javaCode, allowMessage)) + def compileClassesTransformed(scalaCode: String, javaCode: List[(String, String)] = Nil, beforeBackend: global.Tree => global.Tree): List[ClassNode] = + readAsmClasses(compileToBytesTransformed(scalaCode, javaCode, beforeBackend)) + + def compileAsmMethods(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[MethodNode] = { + val c = compileClass(s"class C { $code }", allowMessage = allowMessage) + getAsmMethods(c, _ != "") } - def compileMethods(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[MethodNode] = { - compileClasses(s"class C { $code }", allowMessage = allowMessage).head.methods.asScala.toList.filterNot(_.name == "") + def compileAsmMethod(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): MethodNode = { + val List(m) = compileAsmMethods(code, allowMessage) + m } - def singleMethodInstructions(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[Instruction] = { + def compileMethods(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[Method] = + compileAsmMethods(code, allowMessage).map(convertMethod) + + def compileMethod(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): Method = { val List(m) = compileMethods(code, allowMessage = allowMessage) - instructionsFromMethod(m) + m } - def singleMethod(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): Method = { + def compileInstructions(code: String, allowMessage: StoreReporter#Info => Boolean = _ => false): List[Instruction] = { val List(m) = compileMethods(code, allowMessage = allowMessage) - convertMethod(m) + m.instructions } } @@ -145,7 +162,7 @@ object BytecodeTesting { * The output directory is a physical directory, I have not figured out if / how it's possible to * add a VirtualDirectory to the classpath of a compiler. */ - def compileSeparately(codes: List[String], extraArgs: String = "", allowMessage: StoreReporter#Info => Boolean = _ => false, afterEach: AbstractFile => Unit = _ => ()): List[(String, Array[Byte])] = { + def compileToBytesSeparately(codes: List[String], extraArgs: String = "", allowMessage: StoreReporter#Info => Boolean = _ => false, afterEach: AbstractFile => Unit = _ => ()): List[(String, Array[Byte])] = { val outDir = AbstractFile.getDirectory(TempDir.createTempDir()) val outDirPath = outDir.canonicalPath val argsWithOutDir = extraArgs + s" -d $outDirPath -cp $outDirPath" @@ -162,13 +179,11 @@ object BytecodeTesting { classfiles } - def compileClassesSeparately(codes: List[String], extraArgs: String = "", allowMessage: StoreReporter#Info => Boolean = _ => false, afterEach: AbstractFile => Unit = _ => ()) = { - readAsmClasses(compileSeparately(codes, extraArgs, allowMessage, afterEach)) + def compileClassesSeparately(codes: List[String], extraArgs: String = "", allowMessage: StoreReporter#Info => Boolean = _ => false, afterEach: AbstractFile => Unit = _ => ()): List[ClassNode] = { + readAsmClasses(compileToBytesSeparately(codes, extraArgs, allowMessage, afterEach)) } - def readAsmClasses(classfiles: List[(String, Array[Byte])]) = { - classfiles.map(p => AsmUtils.readClass(p._2)).sortBy(_.name) - } + def readAsmClasses(classfiles: List[(String, Array[Byte])]) = classfiles.map(p => AsmUtils.readClass(p._2)).sortBy(_.name) def assertSameCode(method: Method, expected: List[Instruction]): Unit = assertSameCode(method.instructions.dropNonOp, expected) def assertSameCode(actual: List[Instruction], expected: List[Instruction]): Unit = { @@ -218,23 +233,51 @@ object BytecodeTesting { assert(indy.isEmpty, indy) } - def getSingleMethod(classNode: ClassNode, name: String): Method = - convertMethod(classNode.methods.asScala.toList.find(_.name == name).get) + def findClass(cs: List[ClassNode], name: String): ClassNode = { + val List(c) = cs.filter(_.name == name) + c + } + + def getAsmMethods(c: ClassNode, p: String => Boolean): List[MethodNode] = + c.methods.iterator.asScala.filter(m => p(m.name)).toList.sortBy(_.name) - def findAsmMethods(c: ClassNode, p: String => Boolean) = c.methods.iterator.asScala.filter(m => p(m.name)).toList.sortBy(_.name) - def findAsmMethod(c: ClassNode, name: String) = findAsmMethods(c, _ == name).head + def getAsmMethods(c: ClassNode, name: String): List[MethodNode] = + getAsmMethods(c, _ == name) + + def getAsmMethod(c: ClassNode, name: String): MethodNode = { + val List(m) = getAsmMethods(c, name) + m + } + + def getMethods(c: ClassNode, name: String): List[Method] = + getAsmMethods(c, name).map(convertMethod) + + def getMethod(c: ClassNode, name: String): Method = + convertMethod(getAsmMethod(c, name)) + + def getInstructions(c: ClassNode, name: String): List[Instruction] = + getMethod(c, name).instructions /** * Instructions that match `query` when textified. * If `query` starts with a `+`, the next instruction is returned. */ - def findInstr(method: MethodNode, query: String): List[AbstractInsnNode] = { + def findInstrs(method: MethodNode, query: String): List[AbstractInsnNode] = { val useNext = query(0) == '+' val instrPart = if (useNext) query.drop(1) else query val insns = method.instructions.iterator.asScala.filter(i => textify(i) contains instrPart).toList if (useNext) insns.map(_.getNext) else insns } + /** + * Instruction that matches `query` when textified. + * If `query` starts with a `+`, the next instruction is returned. + */ + def findInstr(method: MethodNode, query: String): AbstractInsnNode = { + val List(i) = findInstrs(method, query) + i + } + def assertHandlerLabelPostions(h: ExceptionHandler, instructions: List[Instruction], startIndex: Int, endIndex: Int, handlerIndex: Int): Unit = { val insVec = instructions.toVector assertTrue(h.start == insVec(startIndex) && h.end == insVec(endIndex) && h.handler == insVec(handlerIndex)) From 0e7964ad9919b3ffd591deaf73f20cfb3e5e0cd0 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 20 May 2016 07:53:44 +0200 Subject: [PATCH 037/153] Small cleanup in JUnit test --- .../backend/jvm/opt/InlinerSeparateCompilationTest.scala | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala index e7c3bab62f6b..b196f1a9ba4d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala @@ -8,13 +8,9 @@ import org.junit.runners.JUnit4 import scala.tools.testing.BytecodeTesting._ -object InlinerSeparateCompilationTest { - val args = "-Yopt:l:classpath" -} - @RunWith(classOf[JUnit4]) class InlinerSeparateCompilationTest { - import InlinerSeparateCompilationTest._ + val args = "-Yopt:l:classpath" @Test def inlnieMixedinMember(): Unit = { From 46d523b47ad835e4124a7d3e1f03f103917fe89d Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 20 May 2016 14:57:28 +0200 Subject: [PATCH 038/153] Cleanup in BytecodeTest --- test/junit/scala/issues/BytecodeTest.scala | 48 +++++++++------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/test/junit/scala/issues/BytecodeTest.scala b/test/junit/scala/issues/BytecodeTest.scala index 0bb87a4ea6a2..125024f746ce 100644 --- a/test/junit/scala/issues/BytecodeTest.scala +++ b/test/junit/scala/issues/BytecodeTest.scala @@ -206,19 +206,13 @@ class BytecodeTest extends BytecodeTesting { Label(17), Op(IRETURN))) } - object forwarderTestUtils { - import language.implicitConversions - implicit def s2c(s: Symbol)(implicit classes: Map[String, ClassNode]): ClassNode = classes(s.name) - - def checkForwarder(c: ClassNode, target: String) = { - val List(f) = getMethods(c, "f") - assertSameCode(f, List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, target, "f", "()I", false), Op(IRETURN))) - } + def checkForwarder(classes: Map[String, ClassNode], clsName: Symbol, target: String) = { + val List(f) = getMethods(classes(clsName.name), "f") + assertSameCode(f, List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, target, "f", "()I", false), Op(IRETURN))) } @Test def traitMethodForwarders(): Unit = { - import forwarderTestUtils._ val code = """trait T1 { def f = 1 } |trait T2 extends T1 { override def f = 2 } @@ -268,27 +262,26 @@ class BytecodeTest extends BytecodeTesting { |class C20 extends T8 """.stripMargin - implicit val classes = compileClasses(code).map(c => (c.name, c)).toMap + val c = compileClasses(code).map(c => (c.name, c)).toMap val noForwarder = List('C1, 'C2, 'C3, 'C4, 'C10, 'C11, 'C12, 'C13, 'C16, 'C17) - for (c <- noForwarder) assertEquals(getMethods(c, "f"), Nil) - - checkForwarder('C5, "T3") - checkForwarder('C6, "T4") - checkForwarder('C7, "T5") - checkForwarder('C8, "T4") - checkForwarder('C9, "T5") - checkForwarder('C14, "T4") - checkForwarder('C15, "T5") - assertSameSummary(getMethod('C18, "f"), List(BIPUSH, IRETURN)) - checkForwarder('C19, "T7") - assertSameCode(getMethod('C19, "T7$$super$f"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "C18", "f", "()I", false), Op(IRETURN))) - assertInvoke(getMethod('C20, "clone"), "T8", "clone") // mixin forwarder + for (cn <- noForwarder) assertEquals(getMethods(c(cn.name), "f"), Nil) + + checkForwarder(c, 'C5, "T3") + checkForwarder(c, 'C6, "T4") + checkForwarder(c, 'C7, "T5") + checkForwarder(c, 'C8, "T4") + checkForwarder(c, 'C9, "T5") + checkForwarder(c, 'C14, "T4") + checkForwarder(c, 'C15, "T5") + assertSameSummary(getMethod(c("C18"), "f"), List(BIPUSH, IRETURN)) + checkForwarder(c, 'C19, "T7") + assertSameCode(getMethod(c("C19"), "T7$$super$f"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "C18", "f", "()I", false), Op(IRETURN))) + assertInvoke(getMethod(c("C20"), "clone"), "T8", "clone") // mixin forwarder } @Test def noTraitMethodForwardersForOverloads(): Unit = { - import forwarderTestUtils._ val code = """trait T1 { def f(x: Int) = 0 } |trait T2 { def f(x: String) = 1 } @@ -300,7 +293,6 @@ class BytecodeTest extends BytecodeTesting { @Test def traitMethodForwardersForJavaDefaultMethods(): Unit = { - import forwarderTestUtils._ val j1 = ("interface J1 { int f(); }", "J1.java") val j2 = ("interface J2 { default int f() { return 1; } }", "J2.java") val j3 = ("interface J3 extends J1 { default int f() { return 2; } }", "J3.java") @@ -326,12 +318,12 @@ class BytecodeTest extends BytecodeTesting { | |class K12 extends J2 with T2 """.stripMargin - implicit val classes = compileClasses(code, List(j1, j2, j3, j4)).map(c => (c.name, c)).toMap + val c = compileClasses(code, List(j1, j2, j3, j4)).map(c => (c.name, c)).toMap val noForwarder = List('K1, 'K2, 'K3, 'K4, 'K5, 'K6, 'K7, 'K8, 'K9, 'K10, 'K11) - for (c <- noForwarder) assertEquals(getMethods(c, "f"), Nil) + for (cn <- noForwarder) assertEquals(getMethods(c(cn.name), "f"), Nil) - checkForwarder('K12, "T2") + checkForwarder(c, 'K12, "T2") } @Test From 2537027195fd1702bbd12ba8e9d6cb3262b03482 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 20 May 2016 15:19:50 +0200 Subject: [PATCH 039/153] Split RunTest and BytecodeTest into parts, put in matching packages. --- test/junit/scala/BoxUnboxTest.scala | 119 --------- .../PartialFunctionSerializationTest.scala | 16 +- test/junit/scala/issues/RunTest.scala | 247 ------------------ .../scala/lang/annotations/BytecodeTest.scala | 80 ++++++ .../scala/lang/annotations/RunTest.scala | 32 +++ .../scala/lang/primitives/BoxUnboxTest.scala | 222 ++++++++++++++++ .../primitives}/PredefAutoboxingTest.scala | 6 +- .../stringinterpol}/StringContextTest.scala | 9 +- .../traits}/BytecodeTest.scala | 242 ++--------------- test/junit/scala/lang/traits/RunTest.scala | 20 ++ test/junit/scala/reflect/ClassOfTest.scala | 124 +++++++++ .../tools/nsc/backend/jvm/BytecodeTest.scala | 140 ++++++++++ .../backend/jvm}/OptimizedBytecodeTest.scala | 13 +- 13 files changed, 660 insertions(+), 610 deletions(-) delete mode 100644 test/junit/scala/BoxUnboxTest.scala delete mode 100644 test/junit/scala/issues/RunTest.scala create mode 100644 test/junit/scala/lang/annotations/BytecodeTest.scala create mode 100644 test/junit/scala/lang/annotations/RunTest.scala create mode 100644 test/junit/scala/lang/primitives/BoxUnboxTest.scala rename test/junit/scala/{ => lang/primitives}/PredefAutoboxingTest.scala (93%) rename test/junit/scala/{ => lang/stringinterpol}/StringContextTest.scala (98%) rename test/junit/scala/{issues => lang/traits}/BytecodeTest.scala (52%) create mode 100644 test/junit/scala/lang/traits/RunTest.scala create mode 100644 test/junit/scala/reflect/ClassOfTest.scala create mode 100644 test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala rename test/junit/scala/{issues => tools/nsc/backend/jvm}/OptimizedBytecodeTest.scala (98%) diff --git a/test/junit/scala/BoxUnboxTest.scala b/test/junit/scala/BoxUnboxTest.scala deleted file mode 100644 index 88b3037e6990..000000000000 --- a/test/junit/scala/BoxUnboxTest.scala +++ /dev/null @@ -1,119 +0,0 @@ -package scala - -import org.junit.Test -import org.junit.Assert._ -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 - -import scala.tools.testing.AssertUtil._ - -@RunWith(classOf[JUnit4]) -class BoxUnboxTest { - def genericNull[T] = null.asInstanceOf[T] // allowed, see SI-4437, point 2 - - @Test - def boxUnboxInt(): Unit = { - val b = new Integer(1) - val u = 1 - - assertEquals(1.toInt, u) - - assertEquals(Predef.int2Integer(1), b) - assertEquals(1: Integer, b) - assertEquals(Int.box(1), b) - assertEquals(1.asInstanceOf[Object], b) - - assertThrows[ClassCastException]("".asInstanceOf[Integer]) - - assertEquals(Predef.Integer2int(b), u) - assertEquals(b: Int, u) - assertEquals(Int.unbox(b), u) - assertEquals(b.asInstanceOf[Int], u) - assertEquals(b.intValue, u) - assertEquals(b.toInt, u) - intWrapper(b).toInt - - assertThrows[ClassCastException](Int.unbox("")) - assertThrows[ClassCastException]("".asInstanceOf[Int]) - - // null unboxing in various positions - - val n1 = Int.unbox(null) - assertEquals(n1, 0) - val n2 = Predef.Integer2int(null) - assertEquals(n2, 0) - val n3 = (null: Integer): Int - assertEquals(n3, 0) - val n4 = null.asInstanceOf[Int] - assertEquals(n4, 0) - val n5 = null.asInstanceOf[Int] == 0 - assertTrue(n5) - val n6 = null.asInstanceOf[Int] == null - assertFalse(n6) - val n7 = null.asInstanceOf[Int] != 0 - assertFalse(n7) - val n8 = null.asInstanceOf[Int] != null - assertTrue(n8) - - val mp = new java.util.HashMap[Int, Int] - val n9 = mp.get(0) - assertEquals(n9, 0) - val n10 = mp.get(0) == null // SI-602 - assertThrows[AssertionError](assertFalse(n10)) // should not throw - - def f(a: Any) = "" + a - val n11 = f(null.asInstanceOf[Int]) - assertEquals(n11, "0") - - def n12 = genericNull[Int] - assertEquals(n12, 0) - } - - @Test - def numericConversions(): Unit = { - val i1 = 1L.asInstanceOf[Int] - assertEquals(i1, 1) - assertThrows[ClassCastException] { - val i2 = (1L: Any).asInstanceOf[Int] // SI-1448, should not throw. see also SI-4437 point 1. - assertEquals(i2, 1) - } - } - - @Test - def boxUnboxBoolean(): Unit = { - val n1 = Option(null.asInstanceOf[Boolean]) - assertEquals(n1, Some(false)) - } - - @Test - def boxUnboxUnit(): Unit = { - // should not use assertEquals in this test: it takes two Object parameters. normally, Unit does - // not conform to Object, but for Java-defined methods scalac makes an exception and treats them - // as Any. passing a Unit as Any makes the compiler go through another layer of boxing, so it - // can hide some bugs (where we actually have a null, but the compiler makes it a ()). - - var v = 0 - def eff() = { v = 1 } - def chk() = { assert(v == 1); v = 0 } - - val b = runtime.BoxedUnit.UNIT - - assert(eff() == b); chk() - assert(Unit.box(eff()) == b); chk() - assert(().asInstanceOf[Object] == b) - - Unit.unbox({eff(); b}); chk() - Unit.unbox({eff(); null}); chk() - assertThrows[ClassCastException](Unit.unbox({eff(); ""})); chk() - - val n1 = null.asInstanceOf[Unit] - assert(n1 == b) - - val n2 = null.asInstanceOf[Unit] == b - assert(n2) - - def f(a: Any) = "" + a - val n3 = f(null.asInstanceOf[Unit]) - assertEquals(n3, "()") - } -} diff --git a/test/junit/scala/PartialFunctionSerializationTest.scala b/test/junit/scala/PartialFunctionSerializationTest.scala index d525b045cd9c..2019e3a4259c 100644 --- a/test/junit/scala/PartialFunctionSerializationTest.scala +++ b/test/junit/scala/PartialFunctionSerializationTest.scala @@ -7,24 +7,18 @@ import org.junit.runners.JUnit4 @RunWith(classOf[JUnit4]) class PartialFunctionSerializationTest { - val pf1: PartialFunction[Int, Int] = { - case n if n > 0 => 1 - } - - val pf2: PartialFunction[Int, Int] = { - case n if n <= 0 => 2 - } + val pf1: PartialFunction[Int, Int] = { case n if n > 0 => 1 } + val pf2: PartialFunction[Int, Int] = { case n if n <= 0 => 2 } - private def assertSerializable[A,B](fn: A => B) = { + private def assertSerializable[A,B](fn: A => B): Unit = { import java.io._ - new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(fn) } - @Test def canSerializeLiteral= assertSerializable(pf1) + @Test def canSerializeLiteral = assertSerializable(pf1) - @Test def canSerializeLifted= assertSerializable(pf1.lift) + @Test def canSerializeLifted = assertSerializable(pf1.lift) @Test def canSerializeOrElse = assertSerializable(pf1 orElse pf2) diff --git a/test/junit/scala/issues/RunTest.scala b/test/junit/scala/issues/RunTest.scala deleted file mode 100644 index 0686d73d9bdf..000000000000 --- a/test/junit/scala/issues/RunTest.scala +++ /dev/null @@ -1,247 +0,0 @@ -package scala.issues - -import org.junit.Assert._ -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 - -import scala.tools.testing.RunTesting - -object RunTest { - class VC(val x: Any) extends AnyVal - class VCI(val x: Int) extends AnyVal { override def toString = "" + x } -} - -@RunWith(classOf[JUnit4]) -class RunTest extends RunTesting { - import runner._ - - @Test - def classOfValueClassAlias(): Unit = { - val code = - """import scala.issues.RunTest.VC - |type aVC = VC - |type aInt = Int - |type aInteger = Integer - |classOf[VC] == classOf[aVC] && - | classOf[aInt] == classOf[Int] && - | classOf[aInteger] == classOf[Integer] && - | classOf[aInt] != classOf[aInteger] - """.stripMargin - assertTrue(run[Boolean](code)) - } - - @Test - def classOfFinalVal(): Unit = { - val code = - """class C { - | final val a1 = classOf[Int] - | final val b1 = classOf[List[_]] - | final val c1 = classOf[List[String]] - | final val d1 = classOf[Array[Int]] - | final val e1 = classOf[Array[List[_]]] - | final val f1 = classOf[Array[_]] - | - | val a2 = classOf[Int] - | val b2 = classOf[List[_]] - | val c2 = classOf[List[String]] - | val d2 = classOf[Array[Int]] - | val e2 = classOf[Array[List[_]]] - | val f2 = classOf[Array[_]] - | - | val listC = Class.forName("scala.collection.immutable.List") - | - | val compare = List( - | (a1, a2, Integer.TYPE), - | (b1, b2, listC), - | (c1, c2, listC), - | (d1, d2, Array(1).getClass), - | (e1, e2, Array(List()).getClass), - | (f1, f2, new Object().getClass)) - |} - |(new C).compare - """.stripMargin - type K = Class[_] - val cs = run[List[(K, K, K)]](code) - for ((x, y, z) <- cs) { - assertEquals(x, y) - assertEquals(x, z) - } - } - - @Test - def t9702(): Unit = { - val code = - """import javax.annotation.Resource - |import scala.issues.RunTest.VC - |class C { - | type aList[K] = List[K] - | type aVC = VC - | type aInt = Int - | type aInteger = Integer - | @Resource(`type` = classOf[List[Int]]) def a = 0 - | @Resource(`type` = classOf[List[_]]) def b = 0 - | @Resource(`type` = classOf[aList[_]]) def c = 0 - | @Resource(`type` = classOf[Int]) def d = 0 - | @Resource(`type` = classOf[aInt]) def e = 0 - | @Resource(`type` = classOf[Integer]) def f = 0 - | @Resource(`type` = classOf[aInteger]) def g = 0 - | @Resource(`type` = classOf[VC]) def h = 0 - | @Resource(`type` = classOf[aVC]) def i = 0 - | @Resource(`type` = classOf[Array[Int]]) def j = 0 - | @Resource(`type` = classOf[Array[List[_]]]) def k = 0 - |} - |val c = classOf[C] - |def typeArg(meth: String) = c.getDeclaredMethod(meth).getDeclaredAnnotation(classOf[Resource]).`type` - |('a' to 'k').toList.map(_.toString).map(typeArg) - """.stripMargin - - val l = Class.forName("scala.collection.immutable.List") - val i = Integer.TYPE - val ig = new Integer(1).getClass - val v = new RunTest.VC(1).getClass - val ai = Array(1).getClass - val al = Array(List()).getClass - - // sanity checks - assertEquals(i, classOf[Int]) - assertNotEquals(i, ig) - - assertEquals(run[List[Class[_]]](code), - List(l, l, l, i, i, ig, ig, v, v, ai, al)) - } - - @Test - def annotationInfoNotErased(): Unit = { - val code = - """import javax.annotation.Resource - |import scala.annotation.meta.getter - |class C { - | type Rg = Resource @getter - | @(Resource @getter)(`type` = classOf[Int]) def a = 0 - | @Rg(`type` = classOf[Int]) def b = 0 - |} - |val c = classOf[C] - |def typeArg(meth: String) = c.getDeclaredMethod(meth).getDeclaredAnnotation(classOf[Resource]).`type` - |List("a", "b") map typeArg - |""".stripMargin - - val i = Integer.TYPE - assertEquals(run[List[Class[_]]](code), List(i, i)) - } - - @Test - def invocationReceivers(): Unit = { - import invocationReceiversTestCode._ - assertEquals(run[String](definitions("Object") + runCode), "hi" * 9) - assertEquals(run[String](definitions("String") + runCode), "hi" * 9) // bridge method for clone generated - } - - @Test - def classOfUnitConstant(): Unit = { - val code = - """abstract class A { def f: Class[_] } - |class C extends A { final val f = classOf[Unit] } - |val c = new C - |(c.f, (c: A).f) - """.stripMargin - val u = Void.TYPE - assertEquals(run[(Class[_], Class[_])](code), (u, u)) - } - - @Test - def t9671(): Unit = { - val code = - """import scala.issues.RunTest.VCI - | - |def f1(a: Any) = "" + a - |def f2(a: AnyVal) = "" + a - |def f3[T](a: T) = "" + a - |def f4(a: Int) = "" + a - |def f5(a: VCI) = "" + a - |def f6(u: Unit) = "" + u - | - |def n1: AnyRef = null - |def n2: Null = null - |def n3: Any = null - |def n4[T]: T = null.asInstanceOf[T] - | - |def npe(s: => String) = try { s; throw new Error() } catch { case _: NullPointerException => "npe" } - | - | f1(null.asInstanceOf[Int]) + - | f1( n1.asInstanceOf[Int]) + - | f1( n2.asInstanceOf[Int]) + - | f1( n3.asInstanceOf[Int]) + - | f1( n4[Int]) + // "null" - |"-" + - | f1(null.asInstanceOf[VCI]) + - |npe(f1( n1.asInstanceOf[VCI])) + // SI-8097 - | f1( n2.asInstanceOf[VCI]) + - |npe(f1( n3.asInstanceOf[VCI])) + // SI-8097 - | f1( n4[VCI]) + // "null" - |"-" + - | f1(null.asInstanceOf[Unit]) + - | f1( n1.asInstanceOf[Unit]) + - | f1( n2.asInstanceOf[Unit]) + - | f1( n3.asInstanceOf[Unit]) + - | f1( n4[Unit]) + // "null" - |"-" + - | f2(null.asInstanceOf[Int]) + - | f2( n1.asInstanceOf[Int]) + - | f2( n2.asInstanceOf[Int]) + - | f2( n3.asInstanceOf[Int]) + - | f2( n4[Int]) + // "null" - |"-" + - | f2(null.asInstanceOf[VCI]) + - |npe(f2( n1.asInstanceOf[VCI])) + // SI-8097 - | f2( n2.asInstanceOf[VCI]) + - |npe(f2( n3.asInstanceOf[VCI])) + // SI-8097 - | f2( n4[VCI]) + // "null" - |"-" + - | f2(null.asInstanceOf[Unit]) + - | f2( n1.asInstanceOf[Unit]) + - | f2( n2.asInstanceOf[Unit]) + - | f2( n3.asInstanceOf[Unit]) + - | f2( n4[Unit]) + // "null" - |"-" + - | f3(null.asInstanceOf[Int]) + - | f3( n1.asInstanceOf[Int]) + - | f3( n2.asInstanceOf[Int]) + - | f3( n3.asInstanceOf[Int]) + - | f3( n4[Int]) + // "null" - |"-" + - | f3(null.asInstanceOf[VCI]) + - |npe(f3( n1.asInstanceOf[VCI])) + // SI-8097 - | f3( n2.asInstanceOf[VCI]) + - |npe(f3( n3.asInstanceOf[VCI])) + // SI-8097 - | f3( n4[VCI]) + // "null" - |"-" + - | f3(null.asInstanceOf[Unit]) + - | f3( n1.asInstanceOf[Unit]) + - | f3( n2.asInstanceOf[Unit]) + - | f3( n3.asInstanceOf[Unit]) + - | f3( n4[Unit]) + // "null" - |"-" + - | f4(null.asInstanceOf[Int]) + - | f4( n1.asInstanceOf[Int]) + - | f4( n2.asInstanceOf[Int]) + - | f4( n3.asInstanceOf[Int]) + - | f4( n4[Int]) + - |"-" + - | f5(null.asInstanceOf[VCI]) + - |npe(f5( n1.asInstanceOf[VCI])) + // SI-8097 - | f5( n2.asInstanceOf[VCI]) + - |npe(f5( n3.asInstanceOf[VCI])) + // SI-8097 - |npe(f5( n4[VCI])) + // SI-8097 - |"-" + - | f6(null.asInstanceOf[Unit]) + - | f6( n1.asInstanceOf[Unit]) + - | f6( n2.asInstanceOf[Unit]) + - | f6( n3.asInstanceOf[Unit]) + - | f6( n4[Unit]) // "null" - """.stripMargin - - assertEquals(run[String](code), - "0000null-0npe0npenull-()()()()null-0000null-0npe0npenull-()()()()null-0000null-0npe0npenull-()()()()null-00000-0npe0npenpe-()()()()null") - } -} diff --git a/test/junit/scala/lang/annotations/BytecodeTest.scala b/test/junit/scala/lang/annotations/BytecodeTest.scala new file mode 100644 index 000000000000..09fc1d35724f --- /dev/null +++ b/test/junit/scala/lang/annotations/BytecodeTest.scala @@ -0,0 +1,80 @@ +package scala.lang.annotations + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.collection.JavaConverters._ +import scala.tools.nsc.backend.jvm.AsmUtils +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ + +@RunWith(classOf[JUnit4]) +class BytecodeTest extends BytecodeTesting { + import compiler._ + + @Test + def t8731(): Unit = { + val code = + """class C { + | def f(x: Int) = (x: @annotation.switch) match { + | case 1 => 0 + | case 2 => 1 + | case 3 => 2 + | } + | final val K = 10 + | def g(x: Int) = (x: @annotation.switch) match { + | case K => 0 + | case 1 => 10 + | case 2 => 20 + | } + |} + """.stripMargin + + val c = compileClass(code) + + assertTrue(getInstructions(c, "f").count(_.isInstanceOf[TableSwitch]) == 1) + assertTrue(getInstructions(c, "g").count(_.isInstanceOf[LookupSwitch]) == 1) + } + + @Test + def t8926(): Unit = { + import scala.reflect.internal.util.BatchSourceFile + + // this test cannot be implemented using partest because of its mixed-mode compilation strategy: + // partest first compiles all files with scalac, then the java files, and then again the scala + // using the output classpath. this shadows the bug SI-8926. + + val annotA = + """import java.lang.annotation.Retention; + |import java.lang.annotation.RetentionPolicy; + |@Retention(RetentionPolicy.RUNTIME) + |public @interface AnnotA { } + """.stripMargin + val annotB = "public @interface AnnotB { }" + + val scalaSrc = + """@AnnotA class A + |@AnnotB class B + """.stripMargin + + val run = new global.Run() + run.compileSources(List(new BatchSourceFile("AnnotA.java", annotA), new BatchSourceFile("AnnotB.java", annotB), new BatchSourceFile("Test.scala", scalaSrc))) + val outDir = global.settings.outputDirs.getSingleOutput.get + val outfiles = (for (f <- outDir.iterator if !f.isDirectory) yield (f.name, f.toByteArray)).toList + + def check(classfile: String, annotName: String) = { + val f = (outfiles collect { case (`classfile`, bytes) => AsmUtils.readClass(bytes) }).head + val descs = f.visibleAnnotations.asScala.map(_.desc).toList + assertTrue(descs.toString, descs exists (_ contains annotName)) + } + + check("A.class", "AnnotA") + + // known issue SI-8928: the visibility of AnnotB should be CLASS, but annotation classes without + // a @Retention annotation are currently emitted as RUNTIME. + check("B.class", "AnnotB") + } +} \ No newline at end of file diff --git a/test/junit/scala/lang/annotations/RunTest.scala b/test/junit/scala/lang/annotations/RunTest.scala new file mode 100644 index 000000000000..0d9c0c471362 --- /dev/null +++ b/test/junit/scala/lang/annotations/RunTest.scala @@ -0,0 +1,32 @@ +package scala.lang.annotations + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.testing.RunTesting + +@RunWith(classOf[JUnit4]) +class RunTest extends RunTesting { + import runner._ + + @Test + def annotationInfoNotErased(): Unit = { + val code = + """import javax.annotation.Resource + |import scala.annotation.meta.getter + |class C { + | type Rg = Resource @getter + | @(Resource @getter)(`type` = classOf[Int]) def a = 0 + | @Rg(`type` = classOf[Int]) def b = 0 + |} + |val c = classOf[C] + |def typeArg(meth: String) = c.getDeclaredMethod(meth).getDeclaredAnnotation(classOf[Resource]).`type` + |List("a", "b") map typeArg + |""".stripMargin + + val i = Integer.TYPE + assertEquals(run[List[Class[_]]](code), List(i, i)) + } +} diff --git a/test/junit/scala/lang/primitives/BoxUnboxTest.scala b/test/junit/scala/lang/primitives/BoxUnboxTest.scala new file mode 100644 index 000000000000..23c9326989ee --- /dev/null +++ b/test/junit/scala/lang/primitives/BoxUnboxTest.scala @@ -0,0 +1,222 @@ +package scala.lang.primitives + +import org.junit.Test +import org.junit.Assert._ +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.testing.AssertUtil._ +import scala.tools.testing.RunTesting + +object BoxUnboxTest { + class VCI(val x: Int) extends AnyVal { override def toString = "" + x } +} + +@RunWith(classOf[JUnit4]) +class BoxUnboxTest extends RunTesting { + import runner._ + + def genericNull[T] = null.asInstanceOf[T] // allowed, see SI-4437, point 2 + + @Test + def boxUnboxInt(): Unit = { + val b = new Integer(1) + val u = 1 + + assertEquals(1.toInt, u) + + assertEquals(Predef.int2Integer(1), b) + assertEquals(1: Integer, b) + assertEquals(Int.box(1), b) + assertEquals(1.asInstanceOf[Object], b) + + assertThrows[ClassCastException]("".asInstanceOf[Integer]) + + assertEquals(Predef.Integer2int(b), u) + assertEquals(b: Int, u) + assertEquals(Int.unbox(b), u) + assertEquals(b.asInstanceOf[Int], u) + assertEquals(b.intValue, u) + assertEquals(b.toInt, u) + intWrapper(b).toInt + + assertThrows[ClassCastException](Int.unbox("")) + assertThrows[ClassCastException]("".asInstanceOf[Int]) + + // null unboxing in various positions + + val n1 = Int.unbox(null) + assertEquals(n1, 0) + val n2 = Predef.Integer2int(null) + assertEquals(n2, 0) + val n3 = (null: Integer): Int + assertEquals(n3, 0) + val n4 = null.asInstanceOf[Int] + assertEquals(n4, 0) + val n5 = null.asInstanceOf[Int] == 0 + assertTrue(n5) + val n6 = null.asInstanceOf[Int] == null + assertFalse(n6) + val n7 = null.asInstanceOf[Int] != 0 + assertFalse(n7) + val n8 = null.asInstanceOf[Int] != null + assertTrue(n8) + + val mp = new java.util.HashMap[Int, Int] + val n9 = mp.get(0) + assertEquals(n9, 0) + val n10 = mp.get(0) == null // SI-602 + assertThrows[AssertionError](assertFalse(n10)) // should not throw + + def f(a: Any) = "" + a + val n11 = f(null.asInstanceOf[Int]) + assertEquals(n11, "0") + + def n12 = genericNull[Int] + assertEquals(n12, 0) + } + + @Test + def numericConversions(): Unit = { + val i1 = 1L.asInstanceOf[Int] + assertEquals(i1, 1) + assertThrows[ClassCastException] { + val i2 = (1L: Any).asInstanceOf[Int] // SI-1448, should not throw. see also SI-4437 point 1. + assertEquals(i2, 1) + } + } + + @Test + def boxUnboxBoolean(): Unit = { + val n1 = Option(null.asInstanceOf[Boolean]) + assertEquals(n1, Some(false)) + } + + @Test + def boxUnboxUnit(): Unit = { + // should not use assertEquals in this test: it takes two Object parameters. normally, Unit does + // not conform to Object, but for Java-defined methods scalac makes an exception and treats them + // as Any. passing a Unit as Any makes the compiler go through another layer of boxing, so it + // can hide some bugs (where we actually have a null, but the compiler makes it a ()). + + var v = 0 + def eff() = { v = 1 } + def chk() = { assert(v == 1); v = 0 } + + val b = runtime.BoxedUnit.UNIT + + assert(eff() == b); chk() + assert(Unit.box(eff()) == b); chk() + assert(().asInstanceOf[Object] == b) + + Unit.unbox({eff(); b}); chk() + Unit.unbox({eff(); null}); chk() + assertThrows[ClassCastException](Unit.unbox({eff(); ""})); chk() + + val n1 = null.asInstanceOf[Unit] + assert(n1 == b) + + val n2 = null.asInstanceOf[Unit] == b + assert(n2) + + def f(a: Any) = "" + a + val n3 = f(null.asInstanceOf[Unit]) + assertEquals(n3, "()") + } + + @Test + def t9671(): Unit = { + val code = + """import scala.lang.primitives.BoxUnboxTest.VCI + | + |def f1(a: Any) = "" + a + |def f2(a: AnyVal) = "" + a + |def f3[T](a: T) = "" + a + |def f4(a: Int) = "" + a + |def f5(a: VCI) = "" + a + |def f6(u: Unit) = "" + u + | + |def n1: AnyRef = null + |def n2: Null = null + |def n3: Any = null + |def n4[T]: T = null.asInstanceOf[T] + | + |def npe(s: => String) = try { s; throw new Error() } catch { case _: NullPointerException => "npe" } + | + | f1(null.asInstanceOf[Int]) + + | f1( n1.asInstanceOf[Int]) + + | f1( n2.asInstanceOf[Int]) + + | f1( n3.asInstanceOf[Int]) + + | f1( n4[Int]) + // "null" + |"-" + + | f1(null.asInstanceOf[VCI]) + + |npe(f1( n1.asInstanceOf[VCI])) + // SI-8097 + | f1( n2.asInstanceOf[VCI]) + + |npe(f1( n3.asInstanceOf[VCI])) + // SI-8097 + | f1( n4[VCI]) + // "null" + |"-" + + | f1(null.asInstanceOf[Unit]) + + | f1( n1.asInstanceOf[Unit]) + + | f1( n2.asInstanceOf[Unit]) + + | f1( n3.asInstanceOf[Unit]) + + | f1( n4[Unit]) + // "null" + |"-" + + | f2(null.asInstanceOf[Int]) + + | f2( n1.asInstanceOf[Int]) + + | f2( n2.asInstanceOf[Int]) + + | f2( n3.asInstanceOf[Int]) + + | f2( n4[Int]) + // "null" + |"-" + + | f2(null.asInstanceOf[VCI]) + + |npe(f2( n1.asInstanceOf[VCI])) + // SI-8097 + | f2( n2.asInstanceOf[VCI]) + + |npe(f2( n3.asInstanceOf[VCI])) + // SI-8097 + | f2( n4[VCI]) + // "null" + |"-" + + | f2(null.asInstanceOf[Unit]) + + | f2( n1.asInstanceOf[Unit]) + + | f2( n2.asInstanceOf[Unit]) + + | f2( n3.asInstanceOf[Unit]) + + | f2( n4[Unit]) + // "null" + |"-" + + | f3(null.asInstanceOf[Int]) + + | f3( n1.asInstanceOf[Int]) + + | f3( n2.asInstanceOf[Int]) + + | f3( n3.asInstanceOf[Int]) + + | f3( n4[Int]) + // "null" + |"-" + + | f3(null.asInstanceOf[VCI]) + + |npe(f3( n1.asInstanceOf[VCI])) + // SI-8097 + | f3( n2.asInstanceOf[VCI]) + + |npe(f3( n3.asInstanceOf[VCI])) + // SI-8097 + | f3( n4[VCI]) + // "null" + |"-" + + | f3(null.asInstanceOf[Unit]) + + | f3( n1.asInstanceOf[Unit]) + + | f3( n2.asInstanceOf[Unit]) + + | f3( n3.asInstanceOf[Unit]) + + | f3( n4[Unit]) + // "null" + |"-" + + | f4(null.asInstanceOf[Int]) + + | f4( n1.asInstanceOf[Int]) + + | f4( n2.asInstanceOf[Int]) + + | f4( n3.asInstanceOf[Int]) + + | f4( n4[Int]) + + |"-" + + | f5(null.asInstanceOf[VCI]) + + |npe(f5( n1.asInstanceOf[VCI])) + // SI-8097 + | f5( n2.asInstanceOf[VCI]) + + |npe(f5( n3.asInstanceOf[VCI])) + // SI-8097 + |npe(f5( n4[VCI])) + // SI-8097 + |"-" + + | f6(null.asInstanceOf[Unit]) + + | f6( n1.asInstanceOf[Unit]) + + | f6( n2.asInstanceOf[Unit]) + + | f6( n3.asInstanceOf[Unit]) + + | f6( n4[Unit]) // "null" + """.stripMargin + + assertEquals(run[String](code), + "0000null-0npe0npenull-()()()()null-0000null-0npe0npenull-()()()()null-0000null-0npe0npenull-()()()()null-00000-0npe0npenpe-()()()()null") + } +} diff --git a/test/junit/scala/PredefAutoboxingTest.scala b/test/junit/scala/lang/primitives/PredefAutoboxingTest.scala similarity index 93% rename from test/junit/scala/PredefAutoboxingTest.scala rename to test/junit/scala/lang/primitives/PredefAutoboxingTest.scala index e5d8ded5d4e9..ab31a9e8f13a 100644 --- a/test/junit/scala/PredefAutoboxingTest.scala +++ b/test/junit/scala/lang/primitives/PredefAutoboxingTest.scala @@ -1,12 +1,10 @@ -package scala +package scala.lang.primitives -import org.junit.Test import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import scala.tools.testing.AssertUtil._ - @RunWith(classOf[JUnit4]) class PredefAutoboxingTest { @Test def unboxNullByte() = diff --git a/test/junit/scala/StringContextTest.scala b/test/junit/scala/lang/stringinterpol/StringContextTest.scala similarity index 98% rename from test/junit/scala/StringContextTest.scala rename to test/junit/scala/lang/stringinterpol/StringContextTest.scala index b5af6de7eb23..d2cb8149d7e4 100644 --- a/test/junit/scala/StringContextTest.scala +++ b/test/junit/scala/lang/stringinterpol/StringContextTest.scala @@ -1,15 +1,14 @@ -package scala +package scala.lang.stringinterpol import java.text.DecimalFormat -import language.implicitConversions - -import org.junit.Test import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 +import scala.language.implicitConversions import scala.tools.testing.AssertUtil._ object StringContextTestUtils { @@ -128,7 +127,7 @@ class StringContextTest { val fff = new java.util.Formattable { def formatTo(f: java.util.Formatter, g: Int, w: Int, p: Int) = f.format("4") } - import java.util.{ Calendar, Locale } + import java.util.{Calendar, Locale} val c = Calendar.getInstance(Locale.US) c.set(2012, Calendar.MAY, 26) implicit def strToDate(x: String): Calendar = c diff --git a/test/junit/scala/issues/BytecodeTest.scala b/test/junit/scala/lang/traits/BytecodeTest.scala similarity index 52% rename from test/junit/scala/issues/BytecodeTest.scala rename to test/junit/scala/lang/traits/BytecodeTest.scala index 125024f746ce..f47fc9c12724 100644 --- a/test/junit/scala/issues/BytecodeTest.scala +++ b/test/junit/scala/lang/traits/BytecodeTest.scala @@ -1,4 +1,4 @@ -package scala.issues +package scala.lang.traits import org.junit.Assert._ import org.junit.Test @@ -9,7 +9,6 @@ import scala.collection.JavaConverters._ import scala.tools.asm.Opcodes import scala.tools.asm.Opcodes._ import scala.tools.asm.tree.ClassNode -import scala.tools.nsc.backend.jvm.AsmUtils import scala.tools.partest.ASMConverters._ import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ @@ -18,194 +17,6 @@ import scala.tools.testing.BytecodeTesting._ class BytecodeTest extends BytecodeTesting { import compiler._ - @Test - def t8731(): Unit = { - val code = - """class C { - | def f(x: Int) = (x: @annotation.switch) match { - | case 1 => 0 - | case 2 => 1 - | case 3 => 2 - | } - | final val K = 10 - | def g(x: Int) = (x: @annotation.switch) match { - | case K => 0 - | case 1 => 10 - | case 2 => 20 - | } - |} - """.stripMargin - - val c = compileClass(code) - - assertTrue(getInstructions(c, "f").count(_.isInstanceOf[TableSwitch]) == 1) - assertTrue(getInstructions(c, "g").count(_.isInstanceOf[LookupSwitch]) == 1) - } - - @Test - def t8926(): Unit = { - import scala.reflect.internal.util.BatchSourceFile - - // this test cannot be implemented using partest because of its mixed-mode compilation strategy: - // partest first compiles all files with scalac, then the java files, and then again the scala - // using the output classpath. this shadows the bug SI-8926. - - val annotA = - """import java.lang.annotation.Retention; - |import java.lang.annotation.RetentionPolicy; - |@Retention(RetentionPolicy.RUNTIME) - |public @interface AnnotA { } - """.stripMargin - val annotB = "public @interface AnnotB { }" - - val scalaSrc = - """@AnnotA class A - |@AnnotB class B - """.stripMargin - - val run = new global.Run() - run.compileSources(List(new BatchSourceFile("AnnotA.java", annotA), new BatchSourceFile("AnnotB.java", annotB), new BatchSourceFile("Test.scala", scalaSrc))) - val outDir = global.settings.outputDirs.getSingleOutput.get - val outfiles = (for (f <- outDir.iterator if !f.isDirectory) yield (f.name, f.toByteArray)).toList - - def check(classfile: String, annotName: String) = { - val f = (outfiles collect { case (`classfile`, bytes) => AsmUtils.readClass(bytes) }).head - val descs = f.visibleAnnotations.asScala.map(_.desc).toList - assertTrue(descs.toString, descs exists (_ contains annotName)) - } - - check("A.class", "AnnotA") - - // known issue SI-8928: the visibility of AnnotB should be CLASS, but annotation classes without - // a @Retention annotation are currently emitted as RUNTIME. - check("B.class", "AnnotB") - } - - @Test - def t6288bJumpPosition(): Unit = { - val code = - """object Case3 { // 01 - | def unapply(z: Any): Option[Int] = Some(-1) // 02 - | def main(args: Array[String]) { // 03 - | ("": Any) match { // 04 - | case x : String => // 05 - | println("case 0") // 06 println and jump at 6 - | case _ => // 07 - | println("default") // 08 println and jump at 8 - | } // 09 - | println("done") // 10 - | } - |} - """.stripMargin - val List(mirror, module) = compileClasses(code) - - val unapplyLineNumbers = getInstructions(module, "unapply").filter(_.isInstanceOf[LineNumber]) - assert(unapplyLineNumbers == List(LineNumber(2, Label(0))), unapplyLineNumbers) - - val expected = List( - LineNumber(4, Label(0)), - LineNumber(5, Label(5)), - Jump(IFEQ, Label(20)), - - LineNumber(6, Label(11)), - Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), - Jump(GOTO, Label(33)), - - LineNumber(5, Label(20)), - Jump(GOTO, Label(24)), - - LineNumber(8, Label(24)), - Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), - Jump(GOTO, Label(33)), - - LineNumber(10, Label(33)), - Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false) - ) - - val mainIns = getInstructions(module, "main") filter { - case _: LineNumber | _: Invoke | _: Jump => true - case _ => false - } - assertSameCode(mainIns, expected) - } - - @Test - def bytecodeForBranches(): Unit = { - val code = - """class C { - | def t1(b: Boolean) = if (b) 1 else 2 - | def t2(x: Int) = if (x == 393) 1 else 2 - | def t3(a: Array[String], b: AnyRef) = a != b && b == a - | def t4(a: AnyRef) = a == null || null != a - | def t5(a: AnyRef) = (a eq null) || (null ne a) - | def t6(a: Int, b: Boolean) = if ((a == 10) && b || a != 1) 1 else 2 - | def t7(a: AnyRef, b: AnyRef) = a == b - | def t8(a: AnyRef) = Nil == a || "" != a - |} - """.stripMargin - - val c = compileClass(code) - - // t1: no unnecessary GOTOs - assertSameCode(getMethod(c, "t1"), List( - VarOp(ILOAD, 1), Jump(IFEQ, Label(6)), - Op(ICONST_1), Jump(GOTO, Label(9)), - Label(6), Op(ICONST_2), - Label(9), Op(IRETURN))) - - // t2: no unnecessary GOTOs - assertSameCode(getMethod(c, "t2"), List( - VarOp(ILOAD, 1), IntOp(SIPUSH, 393), Jump(IF_ICMPNE, Label(7)), - Op(ICONST_1), Jump(GOTO, Label(10)), - Label(7), Op(ICONST_2), - Label(10), Op(IRETURN))) - - // t3: Array == is translated to reference equality, AnyRef == to null checks and equals - assertSameCode(getMethod(c, "t3"), List( - // Array == - VarOp(ALOAD, 1), VarOp(ALOAD, 2), Jump(IF_ACMPEQ, Label(23)), - // AnyRef == - VarOp(ALOAD, 2), VarOp(ALOAD, 1), VarOp(ASTORE, 3), Op(DUP), Jump(IFNONNULL, Label(14)), - Op(POP), VarOp(ALOAD, 3), Jump(IFNULL, Label(19)), Jump(GOTO, Label(23)), - Label(14), VarOp(ALOAD, 3), Invoke(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false), Jump(IFEQ, Label(23)), - Label(19), Op(ICONST_1), Jump(GOTO, Label(26)), - Label(23), Op(ICONST_0), - Label(26), Op(IRETURN))) - - val t4t5 = List( - VarOp(ALOAD, 1), Jump(IFNULL, Label(6)), - VarOp(ALOAD, 1), Jump(IFNULL, Label(10)), - Label(6), Op(ICONST_1), Jump(GOTO, Label(13)), - Label(10), Op(ICONST_0), - Label(13), Op(IRETURN)) - - // t4: one side is known null, so just a null check on the other - assertSameCode(getMethod(c, "t4"), t4t5) - - // t5: one side known null, so just a null check on the other - assertSameCode(getMethod(c, "t5"), t4t5) - - // t6: no unnecessary GOTOs - assertSameCode(getMethod(c, "t6"), List( - VarOp(ILOAD, 1), IntOp(BIPUSH, 10), Jump(IF_ICMPNE, Label(7)), - VarOp(ILOAD, 2), Jump(IFNE, Label(12)), - Label(7), VarOp(ILOAD, 1), Op(ICONST_1), Jump(IF_ICMPEQ, Label(16)), - Label(12), Op(ICONST_1), Jump(GOTO, Label(19)), - Label(16), Op(ICONST_2), - Label(19), Op(IRETURN))) - - // t7: universal equality - assertInvoke(getMethod(c, "t7"), "scala/runtime/BoxesRunTime", "equals") - - // t8: no null checks invoking equals on modules and constants - assertSameCode(getMethod(c, "t8"), List( - Field(GETSTATIC, "scala/collection/immutable/Nil$", "MODULE$", "Lscala/collection/immutable/Nil$;"), VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false), Jump(IFNE, Label(10)), - Ldc(LDC, ""), VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false), Jump(IFNE, Label(14)), - Label(10), Op(ICONST_1), Jump(GOTO, Label(17)), - Label(14), Op(ICONST_0), - Label(17), Op(IRETURN))) - } - def checkForwarder(classes: Map[String, ClassNode], clsName: Symbol, target: String) = { val List(f) = getMethods(classes(clsName.name), "f") assertSameCode(f, List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, target, "f", "()I", false), Op(IRETURN))) @@ -417,36 +228,37 @@ class BytecodeTest extends BytecodeTesting { // pass `null` to super constructor, no box-unbox, no Integer created List(ALOAD, ILOAD, PUTFIELD, ALOAD, ACONST_NULL, "", RETURN)) } + } object invocationReceiversTestCode { // if cloneType is more specific than Object (e.g., String), a bridge method is generated. def definitions(cloneType: String) = - s"""trait T { override def clone(): $cloneType = "hi" } - |trait U extends T - |class C1 extends U with Cloneable { - | // The comments below are true when $cloneType is Object. - | // C1 gets a forwarder for clone that invokes T.clone. this is needed because JVM method - | // resolution always prefers class members, so it would resolve to Object.clone, even if - | // C1 is a subtype of the interface T which has an overriding default method for clone. - | - | // invokeinterface T.clone - | def f1 = (this: T).clone() - | - | // cannot invokeinterface U.clone (NoSuchMethodError). Object.clone would work here, but - | // not in the example in C2 (illegal access to protected). T.clone works in all cases and - | // resolves correctly. - | def f2 = (this: U).clone() - | - | // invokevirtual C1.clone() - | def f3 = (this: C1).clone() - |} - | - |class C2 { - | def f1(t: T) = t.clone() // invokeinterface T.clone - | def f2(t: U) = t.clone() // invokeinterface T.clone -- Object.clone would be illegal (protected, explained in C1) - | def f3(t: C1) = t.clone() // invokevirtual C1.clone -- Object.clone would be illegal - |} + s"""trait T { override def clone(): $cloneType = "hi" } + |trait U extends T + |class C1 extends U with Cloneable { + | // The comments below are true when $cloneType is Object. + | // C1 gets a forwarder for clone that invokes T.clone. this is needed because JVM method + | // resolution always prefers class members, so it would resolve to Object.clone, even if + | // C1 is a subtype of the interface T which has an overriding default method for clone. + | + | // invokeinterface T.clone + | def f1 = (this: T).clone() + | + | // cannot invokeinterface U.clone (NoSuchMethodError). Object.clone would work here, but + | // not in the example in C2 (illegal access to protected). T.clone works in all cases and + | // resolves correctly. + | def f2 = (this: U).clone() + | + | // invokevirtual C1.clone() + | def f3 = (this: C1).clone() + |} + | + |class C2 { + | def f1(t: T) = t.clone() // invokeinterface T.clone + | def f2(t: U) = t.clone() // invokeinterface T.clone -- Object.clone would be illegal (protected, explained in C1) + | def f3(t: C1) = t.clone() // invokevirtual C1.clone -- Object.clone would be illegal + |} """.stripMargin val runCode = diff --git a/test/junit/scala/lang/traits/RunTest.scala b/test/junit/scala/lang/traits/RunTest.scala new file mode 100644 index 000000000000..d27dc15e202d --- /dev/null +++ b/test/junit/scala/lang/traits/RunTest.scala @@ -0,0 +1,20 @@ +package scala.lang.traits + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.testing.RunTesting + +@RunWith(classOf[JUnit4]) +class RunTest extends RunTesting { + import runner._ + + @Test + def invocationReceivers(): Unit = { + import invocationReceiversTestCode._ + assertEquals(run[String](definitions("Object") + runCode), "hi" * 9) + assertEquals(run[String](definitions("String") + runCode), "hi" * 9) // bridge method for clone generated + } +} diff --git a/test/junit/scala/reflect/ClassOfTest.scala b/test/junit/scala/reflect/ClassOfTest.scala new file mode 100644 index 000000000000..520b14ccd467 --- /dev/null +++ b/test/junit/scala/reflect/ClassOfTest.scala @@ -0,0 +1,124 @@ +package scala.reflect + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.testing.RunTesting + +object ClassOfTest { + class VC(val x: Any) extends AnyVal +} + +@RunWith(classOf[JUnit4]) +class ClassOfTest extends RunTesting { + import runner._ + + @Test + def classOfValueClassAlias(): Unit = { + val code = + """import scala.reflect.ClassOfTest.VC + |type aVC = VC + |type aInt = Int + |type aInteger = Integer + |classOf[VC] == classOf[aVC] && + | classOf[aInt] == classOf[Int] && + | classOf[aInteger] == classOf[Integer] && + | classOf[aInt] != classOf[aInteger] + """.stripMargin + assertTrue(run[Boolean](code)) + } + + @Test + def classOfFinalVal(): Unit = { + val code = + """class C { + | final val a1 = classOf[Int] + | final val b1 = classOf[List[_]] + | final val c1 = classOf[List[String]] + | final val d1 = classOf[Array[Int]] + | final val e1 = classOf[Array[List[_]]] + | final val f1 = classOf[Array[_]] + | + | val a2 = classOf[Int] + | val b2 = classOf[List[_]] + | val c2 = classOf[List[String]] + | val d2 = classOf[Array[Int]] + | val e2 = classOf[Array[List[_]]] + | val f2 = classOf[Array[_]] + | + | val listC = Class.forName("scala.collection.immutable.List") + | + | val compare = List( + | (a1, a2, Integer.TYPE), + | (b1, b2, listC), + | (c1, c2, listC), + | (d1, d2, Array(1).getClass), + | (e1, e2, Array(List()).getClass), + | (f1, f2, new Object().getClass)) + |} + |(new C).compare + """.stripMargin + type K = Class[_] + val cs = run[List[(K, K, K)]](code) + for ((x, y, z) <- cs) { + assertEquals(x, y) + assertEquals(x, z) + } + } + + @Test + def t9702(): Unit = { + val code = + """import javax.annotation.Resource + |import scala.reflect.ClassOfTest.VC + |class C { + | type aList[K] = List[K] + | type aVC = VC + | type aInt = Int + | type aInteger = Integer + | @Resource(`type` = classOf[List[Int]]) def a = 0 + | @Resource(`type` = classOf[List[_]]) def b = 0 + | @Resource(`type` = classOf[aList[_]]) def c = 0 + | @Resource(`type` = classOf[Int]) def d = 0 + | @Resource(`type` = classOf[aInt]) def e = 0 + | @Resource(`type` = classOf[Integer]) def f = 0 + | @Resource(`type` = classOf[aInteger]) def g = 0 + | @Resource(`type` = classOf[VC]) def h = 0 + | @Resource(`type` = classOf[aVC]) def i = 0 + | @Resource(`type` = classOf[Array[Int]]) def j = 0 + | @Resource(`type` = classOf[Array[List[_]]]) def k = 0 + |} + |val c = classOf[C] + |def typeArg(meth: String) = c.getDeclaredMethod(meth).getDeclaredAnnotation(classOf[Resource]).`type` + |('a' to 'k').toList.map(_.toString).map(typeArg) + """.stripMargin + + val l = Class.forName("scala.collection.immutable.List") + val i = Integer.TYPE + val ig = new Integer(1).getClass + val v = new ClassOfTest.VC(1).getClass + val ai = Array(1).getClass + val al = Array(List()).getClass + + // sanity checks + assertEquals(i, classOf[Int]) + assertNotEquals(i, ig) + + assertEquals(run[List[Class[_]]](code), + List(l, l, l, i, i, ig, ig, v, v, ai, al)) + } + + @Test + def classOfUnitConstant(): Unit = { + val code = + """abstract class A { def f: Class[_] } + |class C extends A { final val f = classOf[Unit] } + |val c = new C + |(c.f, (c: A).f) + """.stripMargin + val u = Void.TYPE + assertEquals(run[(Class[_], Class[_])](code), (u, u)) + } +} diff --git a/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala new file mode 100644 index 000000000000..7954fe2360d9 --- /dev/null +++ b/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala @@ -0,0 +1,140 @@ +package scala.tools.nsc.backend.jvm + +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.asm.Opcodes._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting._ + +@RunWith(classOf[JUnit4]) +class BytecodeTest extends BytecodeTesting { + import compiler._ + + @Test + def t6288bJumpPosition(): Unit = { + val code = + """object Case3 { // 01 + | def unapply(z: Any): Option[Int] = Some(-1) // 02 + | def main(args: Array[String]) { // 03 + | ("": Any) match { // 04 + | case x : String => // 05 + | println("case 0") // 06 println and jump at 6 + | case _ => // 07 + | println("default") // 08 println and jump at 8 + | } // 09 + | println("done") // 10 + | } + |} + """.stripMargin + val List(mirror, module) = compileClasses(code) + + val unapplyLineNumbers = getInstructions(module, "unapply").filter(_.isInstanceOf[LineNumber]) + assert(unapplyLineNumbers == List(LineNumber(2, Label(0))), unapplyLineNumbers) + + val expected = List( + LineNumber(4, Label(0)), + LineNumber(5, Label(5)), + Jump(IFEQ, Label(20)), + + LineNumber(6, Label(11)), + Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), + Jump(GOTO, Label(33)), + + LineNumber(5, Label(20)), + Jump(GOTO, Label(24)), + + LineNumber(8, Label(24)), + Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), + Jump(GOTO, Label(33)), + + LineNumber(10, Label(33)), + Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false) + ) + + val mainIns = getInstructions(module, "main") filter { + case _: LineNumber | _: Invoke | _: Jump => true + case _ => false + } + assertSameCode(mainIns, expected) + } + + @Test + def bytecodeForBranches(): Unit = { + val code = + """class C { + | def t1(b: Boolean) = if (b) 1 else 2 + | def t2(x: Int) = if (x == 393) 1 else 2 + | def t3(a: Array[String], b: AnyRef) = a != b && b == a + | def t4(a: AnyRef) = a == null || null != a + | def t5(a: AnyRef) = (a eq null) || (null ne a) + | def t6(a: Int, b: Boolean) = if ((a == 10) && b || a != 1) 1 else 2 + | def t7(a: AnyRef, b: AnyRef) = a == b + | def t8(a: AnyRef) = Nil == a || "" != a + |} + """.stripMargin + + val c = compileClass(code) + + // t1: no unnecessary GOTOs + assertSameCode(getMethod(c, "t1"), List( + VarOp(ILOAD, 1), Jump(IFEQ, Label(6)), + Op(ICONST_1), Jump(GOTO, Label(9)), + Label(6), Op(ICONST_2), + Label(9), Op(IRETURN))) + + // t2: no unnecessary GOTOs + assertSameCode(getMethod(c, "t2"), List( + VarOp(ILOAD, 1), IntOp(SIPUSH, 393), Jump(IF_ICMPNE, Label(7)), + Op(ICONST_1), Jump(GOTO, Label(10)), + Label(7), Op(ICONST_2), + Label(10), Op(IRETURN))) + + // t3: Array == is translated to reference equality, AnyRef == to null checks and equals + assertSameCode(getMethod(c, "t3"), List( + // Array == + VarOp(ALOAD, 1), VarOp(ALOAD, 2), Jump(IF_ACMPEQ, Label(23)), + // AnyRef == + VarOp(ALOAD, 2), VarOp(ALOAD, 1), VarOp(ASTORE, 3), Op(DUP), Jump(IFNONNULL, Label(14)), + Op(POP), VarOp(ALOAD, 3), Jump(IFNULL, Label(19)), Jump(GOTO, Label(23)), + Label(14), VarOp(ALOAD, 3), Invoke(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false), Jump(IFEQ, Label(23)), + Label(19), Op(ICONST_1), Jump(GOTO, Label(26)), + Label(23), Op(ICONST_0), + Label(26), Op(IRETURN))) + + val t4t5 = List( + VarOp(ALOAD, 1), Jump(IFNULL, Label(6)), + VarOp(ALOAD, 1), Jump(IFNULL, Label(10)), + Label(6), Op(ICONST_1), Jump(GOTO, Label(13)), + Label(10), Op(ICONST_0), + Label(13), Op(IRETURN)) + + // t4: one side is known null, so just a null check on the other + assertSameCode(getMethod(c, "t4"), t4t5) + + // t5: one side known null, so just a null check on the other + assertSameCode(getMethod(c, "t5"), t4t5) + + // t6: no unnecessary GOTOs + assertSameCode(getMethod(c, "t6"), List( + VarOp(ILOAD, 1), IntOp(BIPUSH, 10), Jump(IF_ICMPNE, Label(7)), + VarOp(ILOAD, 2), Jump(IFNE, Label(12)), + Label(7), VarOp(ILOAD, 1), Op(ICONST_1), Jump(IF_ICMPEQ, Label(16)), + Label(12), Op(ICONST_1), Jump(GOTO, Label(19)), + Label(16), Op(ICONST_2), + Label(19), Op(IRETURN))) + + // t7: universal equality + assertInvoke(getMethod(c, "t7"), "scala/runtime/BoxesRunTime", "equals") + + // t8: no null checks invoking equals on modules and constants + assertSameCode(getMethod(c, "t8"), List( + Field(GETSTATIC, "scala/collection/immutable/Nil$", "MODULE$", "Lscala/collection/immutable/Nil$;"), VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false), Jump(IFNE, Label(10)), + Ldc(LDC, ""), VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false), Jump(IFNE, Label(14)), + Label(10), Op(ICONST_1), Jump(GOTO, Label(17)), + Label(14), Op(ICONST_0), + Label(17), Op(IRETURN))) + } +} diff --git a/test/junit/scala/issues/OptimizedBytecodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala similarity index 98% rename from test/junit/scala/issues/OptimizedBytecodeTest.scala rename to test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala index af1c50acac37..003162c1ad41 100644 --- a/test/junit/scala/issues/OptimizedBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala @@ -1,18 +1,13 @@ -package scala.issues +package scala.tools.nsc.backend.jvm +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.junit.Test import scala.tools.asm.Opcodes._ -import org.junit.Assert._ - -import scala.tools.nsc.backend.jvm.AsmUtils +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ -import scala.tools.partest.ASMConverters -import ASMConverters._ -import AsmUtils._ -import scala.tools.testing.{BytecodeTesting, ClearAfterClass} @RunWith(classOf[JUnit4]) class OptimizedBytecodeTest extends BytecodeTesting { From 64fdae87975f019d3821ca943852df37d50db801 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 20 May 2016 16:07:25 +0200 Subject: [PATCH 040/153] All JUnit tests pass without bootstrap (when run in intellij, sbt) --- .../scala/lang/primitives/BoxUnboxTest.scala | 203 ++++++++++-------- .../jvm/opt/BTypesFromClassfileTest.scala | 6 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 6 +- 3 files changed, 123 insertions(+), 92 deletions(-) diff --git a/test/junit/scala/lang/primitives/BoxUnboxTest.scala b/test/junit/scala/lang/primitives/BoxUnboxTest.scala index 23c9326989ee..e4911f1af530 100644 --- a/test/junit/scala/lang/primitives/BoxUnboxTest.scala +++ b/test/junit/scala/lang/primitives/BoxUnboxTest.scala @@ -1,11 +1,10 @@ package scala.lang.primitives -import org.junit.Test import org.junit.Assert._ +import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import scala.tools.testing.AssertUtil._ import scala.tools.testing.RunTesting object BoxUnboxTest { @@ -16,80 +15,100 @@ object BoxUnboxTest { class BoxUnboxTest extends RunTesting { import runner._ - def genericNull[T] = null.asInstanceOf[T] // allowed, see SI-4437, point 2 - @Test def boxUnboxInt(): Unit = { - val b = new Integer(1) - val u = 1 - - assertEquals(1.toInt, u) - - assertEquals(Predef.int2Integer(1), b) - assertEquals(1: Integer, b) - assertEquals(Int.box(1), b) - assertEquals(1.asInstanceOf[Object], b) - - assertThrows[ClassCastException]("".asInstanceOf[Integer]) - - assertEquals(Predef.Integer2int(b), u) - assertEquals(b: Int, u) - assertEquals(Int.unbox(b), u) - assertEquals(b.asInstanceOf[Int], u) - assertEquals(b.intValue, u) - assertEquals(b.toInt, u) - intWrapper(b).toInt - - assertThrows[ClassCastException](Int.unbox("")) - assertThrows[ClassCastException]("".asInstanceOf[Int]) - - // null unboxing in various positions - - val n1 = Int.unbox(null) - assertEquals(n1, 0) - val n2 = Predef.Integer2int(null) - assertEquals(n2, 0) - val n3 = (null: Integer): Int - assertEquals(n3, 0) - val n4 = null.asInstanceOf[Int] - assertEquals(n4, 0) - val n5 = null.asInstanceOf[Int] == 0 - assertTrue(n5) - val n6 = null.asInstanceOf[Int] == null - assertFalse(n6) - val n7 = null.asInstanceOf[Int] != 0 - assertFalse(n7) - val n8 = null.asInstanceOf[Int] != null - assertTrue(n8) - - val mp = new java.util.HashMap[Int, Int] - val n9 = mp.get(0) - assertEquals(n9, 0) - val n10 = mp.get(0) == null // SI-602 - assertThrows[AssertionError](assertFalse(n10)) // should not throw - - def f(a: Any) = "" + a - val n11 = f(null.asInstanceOf[Int]) - assertEquals(n11, "0") + // Once we use 2.12.0-M5 as starr, this code can be run directly in the JUnit test. + // Some fixes not yet available in M4 make the test fail when compiled with M4. + val code = + """import scala.tools.testing.AssertUtil._ + |import org.junit.Assert._ + | + |def genericNull[T] = null.asInstanceOf[T] // allowed, see SI-4437, point 2 + | + |val b = new Integer(1) + |val u = 1 + | + |assertEquals(1.toInt, u) + | + |assertEquals(Predef.int2Integer(1), b) + |assertEquals(1: Integer, b) + |assertEquals(Int.box(1), b) + |assertEquals(1.asInstanceOf[Object], b) + | + |assertThrows[ClassCastException]("".asInstanceOf[Integer]) + | + |assertEquals(Predef.Integer2int(b), u) + |assertEquals(b: Int, u) + |assertEquals(Int.unbox(b), u) + |assertEquals(b.asInstanceOf[Int], u) + |assertEquals(b.intValue, u) + |assertEquals(b.toInt, u) + |intWrapper(b).toInt + | + |assertThrows[ClassCastException](Int.unbox("")) + |assertThrows[ClassCastException]("".asInstanceOf[Int]) + | + |// null unboxing in various positions + | + |val n1 = Int.unbox(null) + |assertEquals(n1, 0) + |val n2 = Predef.Integer2int(null) + |assertEquals(n2, 0) + |val n3 = (null: Integer): Int + |assertEquals(n3, 0) + |val n4 = null.asInstanceOf[Int] + |assertEquals(n4, 0) + |val n5 = null.asInstanceOf[Int] == 0 + |assertTrue(n5) + |val n6 = null.asInstanceOf[Int] == null + |assertFalse(n6) + |val n7 = null.asInstanceOf[Int] != 0 + |assertFalse(n7) + |val n8 = null.asInstanceOf[Int] != null + |assertTrue(n8) + | + |val mp = new java.util.HashMap[Int, Int] + |val n9 = mp.get(0) + |assertEquals(n9, 0) + |val n10 = mp.get(0) == null // SI-602 + |assertThrows[AssertionError](assertFalse(n10)) // should not throw + | + |def f(a: Any) = "" + a + |val n11 = f(null.asInstanceOf[Int]) + |assertEquals(n11, "0") + | + |def n12 = genericNull[Int] + |assertEquals(n12, 0) + """.stripMargin - def n12 = genericNull[Int] - assertEquals(n12, 0) + run[Unit](code) } @Test def numericConversions(): Unit = { - val i1 = 1L.asInstanceOf[Int] - assertEquals(i1, 1) - assertThrows[ClassCastException] { - val i2 = (1L: Any).asInstanceOf[Int] // SI-1448, should not throw. see also SI-4437 point 1. - assertEquals(i2, 1) - } + // Once we use 2.12.0-M5 as starr, this code can be run directly in the JUnit test. + val code = + """import scala.tools.testing.AssertUtil._ + |import org.junit.Assert._ + | + |val i1 = 1L.asInstanceOf[Int] + |assertEquals(i1, 1) + |assertThrows[ClassCastException] { + | val i2 = (1L: Any).asInstanceOf[Int] // SI-1448, should not throw. see also SI-4437 point 1. + | assertEquals(i2, 1) + |} + """.stripMargin + run[Unit](code) } @Test def boxUnboxBoolean(): Unit = { - val n1 = Option(null.asInstanceOf[Boolean]) - assertEquals(n1, Some(false)) + // Once we use 2.12.0-M5 as starr, this code can be run directly in the JUnit test. + val code = + """val n1 = Option(null.asInstanceOf[Boolean]) + |n1 + """.stripMargin + assertEquals(run[Option[Boolean]](code), Some(false)) } @Test @@ -99,33 +118,41 @@ class BoxUnboxTest extends RunTesting { // as Any. passing a Unit as Any makes the compiler go through another layer of boxing, so it // can hide some bugs (where we actually have a null, but the compiler makes it a ()). - var v = 0 - def eff() = { v = 1 } - def chk() = { assert(v == 1); v = 0 } - - val b = runtime.BoxedUnit.UNIT - - assert(eff() == b); chk() - assert(Unit.box(eff()) == b); chk() - assert(().asInstanceOf[Object] == b) - - Unit.unbox({eff(); b}); chk() - Unit.unbox({eff(); null}); chk() - assertThrows[ClassCastException](Unit.unbox({eff(); ""})); chk() - - val n1 = null.asInstanceOf[Unit] - assert(n1 == b) - - val n2 = null.asInstanceOf[Unit] == b - assert(n2) - - def f(a: Any) = "" + a - val n3 = f(null.asInstanceOf[Unit]) - assertEquals(n3, "()") + // Once we use 2.12.0-M5 as starr, this code can be run directly in the JUnit test. + val code = + """import scala.tools.testing.AssertUtil._ + |import org.junit.Assert._ + | + |var v = 0 + |def eff() = { v = 1 } + |def chk() = { assert(v == 1); v = 0 } + | + |val b = runtime.BoxedUnit.UNIT + | + |assert(eff() == b); chk() + |assert(Unit.box(eff()) == b); chk() + |assert(().asInstanceOf[Object] == b) + | + |Unit.unbox({eff(); b}); chk() + |Unit.unbox({eff(); null}); chk() + |assertThrows[ClassCastException](Unit.unbox({eff(); ""})); chk() + | + |val n1 = null.asInstanceOf[Unit] + |assert(n1 == b) + | + |val n2 = null.asInstanceOf[Unit] == b + |assert(n2) + | + |def f(a: Any) = "" + a + |val n3 = f(null.asInstanceOf[Unit]) + |assertEquals(n3, "()") + """.stripMargin + run[Unit](code) } @Test def t9671(): Unit = { + // Once we use 2.12.0-M5 as starr, this code can be run directly in the JUnit test. val code = """import scala.lang.primitives.BoxUnboxTest.VCI | diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala index 1169871ecda0..e7aea71e7215 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala @@ -2,7 +2,7 @@ package scala.tools.nsc package backend.jvm package opt -import org.junit.Test +import org.junit.{Ignore, Test} import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -83,7 +83,9 @@ class BTypesFromClassfileTest extends BytecodeTesting { sameBType(fromSymbol, fromClassfile) } - @Test + // Can be enabled when using 2.12.0-M5 as starr. This test works under a full boostrap, but not + // when compiled with M4. + @Test @Ignore def compareClassBTypes(): Unit = { // Note that not only these classes are tested, but also all their parents and all nested // classes in their InnerClass attributes. diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 24e889cf186e..4e014d452983 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -3,7 +3,7 @@ package backend.jvm package opt import org.junit.Assert._ -import org.junit.Test +import org.junit.{Ignore, Test} import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -1488,7 +1488,9 @@ class InlinerTest extends BytecodeTesting { assertSameSummary(getMethod(c, "t"), List(NEW, "", ICONST_1, IRETURN)) // ICONST_1, U.f is inlined (not T.f) } - @Test + // Can be enabled when using 2.12.0-M5 as starr. This test works under a full boostrap, but not + // when compiled with M4. + @Test @Ignore def inlineArrayForeach(): Unit = { val code = """class C { From e26835c01254ecb4d9b4fa3a8bbe9c835f808a38 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 20 May 2016 16:26:20 +0200 Subject: [PATCH 041/153] Adapt naming convention for collection.convert null safety test Test classes not ending in "Test" are not executed in sbt. IntelliJ runs them. After this patch: 803 tests executed both in sbt and junit. --- .../collection/convert/NullSafetyTest.scala | 279 ------------------ .../convert/NullSafetyToJavaTest.scala | 138 +++++++++ .../convert/NullSafetyToScalaTest.scala | 148 ++++++++++ 3 files changed, 286 insertions(+), 279 deletions(-) delete mode 100644 test/junit/scala/collection/convert/NullSafetyTest.scala create mode 100644 test/junit/scala/collection/convert/NullSafetyToJavaTest.scala create mode 100644 test/junit/scala/collection/convert/NullSafetyToScalaTest.scala diff --git a/test/junit/scala/collection/convert/NullSafetyTest.scala b/test/junit/scala/collection/convert/NullSafetyTest.scala deleted file mode 100644 index 173568408c19..000000000000 --- a/test/junit/scala/collection/convert/NullSafetyTest.scala +++ /dev/null @@ -1,279 +0,0 @@ -package scala.collection.convert - -import java.{util => ju, lang => jl} -import ju.{concurrent => juc} - -import org.junit.Test -import org.junit.experimental.runners.Enclosed -import org.junit.runner.RunWith - -import collection.convert.ImplicitConversions._ -import scala.collection.JavaConverters._ -import scala.collection.{mutable, concurrent} - -@RunWith(classOf[Enclosed]) -object NullSafetyTest { - - /* - * Pertinent: SI-9113 - * Tests to insure that wrappers return null instead of wrapping it as a collection - */ - - class ToScala { - - @Test def testIteratorWrapping(): Unit = { - val nullJIterator: ju.Iterator[AnyRef] = null - val iterator: Iterator[AnyRef] = nullJIterator - - assert(iterator == null) - } - - @Test def testEnumerationWrapping(): Unit = { - val nullJEnumeration: ju.Enumeration[AnyRef] = null - val enumeration: Iterator[AnyRef] = nullJEnumeration - - assert(enumeration == null) - } - - @Test def testIterableWrapping(): Unit = { - val nullJIterable: jl.Iterable[AnyRef] = null - val iterable: Iterable[AnyRef] = nullJIterable - - assert(iterable == null) - } - - @Test def testCollectionWrapping(): Unit = { - val nullJCollection: ju.Collection[AnyRef] = null - val collection: Iterable[AnyRef] = nullJCollection - - assert(collection == null) - } - - @Test def testBufferWrapping(): Unit = { - val nullJList: ju.List[AnyRef] = null - val buffer: mutable.Buffer[AnyRef] = nullJList - - assert(buffer == null) - } - - @Test def testSetWrapping(): Unit = { - val nullJSet: ju.Set[AnyRef] = null - val set: mutable.Set[AnyRef] = nullJSet - - assert(set == null) - } - - @Test def testMapWrapping(): Unit = { - val nullJMap: ju.Map[AnyRef, AnyRef] = null - val map: mutable.Map[AnyRef, AnyRef] = nullJMap - - assert(map == null) - } - - @Test def testConcurrentMapWrapping(): Unit = { - val nullJConMap: juc.ConcurrentMap[AnyRef, AnyRef] = null - val conMap: concurrent.Map[AnyRef, AnyRef] = nullJConMap - - assert(conMap == null) - } - - @Test def testDictionaryWrapping(): Unit = { - val nullJDict: ju.Dictionary[AnyRef, AnyRef] = null - val dict: mutable.Map[AnyRef, AnyRef] = nullJDict - - assert(dict == null) - } - - - @Test def testPropertyWrapping(): Unit = { - val nullJProps: ju.Properties = null - val props: mutable.Map[String, String] = nullJProps - - assert(props == null) - } - - @Test def testIteratorDecoration(): Unit = { - val nullJIterator: ju.Iterator[AnyRef] = null - - assert(nullJIterator.asScala == null) - } - - @Test def testEnumerationDecoration(): Unit = { - val nullJEnumeration: ju.Enumeration[AnyRef] = null - - assert(nullJEnumeration.asScala == null) - } - - @Test def testIterableDecoration(): Unit = { - val nullJIterable: jl.Iterable[AnyRef] = null - - assert(nullJIterable.asScala == null) - } - - @Test def testCollectionDecoration(): Unit = { - val nullJCollection: ju.Collection[AnyRef] = null - - assert(nullJCollection.asScala == null) - } - - @Test def testBufferDecoration(): Unit = { - val nullJBuffer: ju.List[AnyRef] = null - - assert(nullJBuffer.asScala == null) - } - - @Test def testSetDecoration(): Unit = { - val nullJSet: ju.Set[AnyRef] = null - - assert(nullJSet.asScala == null) - } - - @Test def testMapDecoration(): Unit = { - val nullJMap: ju.Map[AnyRef, AnyRef] = null - - assert(nullJMap.asScala == null) - } - - @Test def testConcurrentMapDecoration(): Unit = { - val nullJConMap: juc.ConcurrentMap[AnyRef, AnyRef] = null - - assert(nullJConMap.asScala == null) - } - - @Test def testDictionaryDecoration(): Unit = { - val nullJDict: ju.Dictionary[AnyRef, AnyRef] = null - - assert(nullJDict.asScala == null) - } - - @Test def testPropertiesDecoration(): Unit = { - val nullJProperties: ju.Properties = null - - assert(nullJProperties.asScala == null) - } - } - - class ToJava { - - @Test def testIteratorWrapping(): Unit = { - val nullIterator: Iterator[AnyRef] = null - val jIterator: ju.Iterator[AnyRef] = nullIterator - - assert(jIterator == null) - } - - @Test def testEnumerationWrapping(): Unit = { - val nullEnumeration: Iterator[AnyRef] = null - val enumeration: ju.Iterator[AnyRef] = nullEnumeration - - assert(enumeration == null) - } - - @Test def testIterableWrapping(): Unit = { - val nullIterable: Iterable[AnyRef] = null - val iterable: jl.Iterable[AnyRef] = asJavaIterable(nullIterable) - - assert(iterable == null) - } - - @Test def testCollectionWrapping(): Unit = { - val nullCollection: Iterable[AnyRef] = null - val collection: ju.Collection[AnyRef] = nullCollection - - assert(collection == null) - } - - @Test def testBufferWrapping(): Unit = { - val nullList: mutable.Buffer[AnyRef] = null - val buffer: ju.List[AnyRef] = nullList - - assert(buffer == null) - } - - @Test def testSetWrapping(): Unit = { - val nullSet: mutable.Set[AnyRef] = null - val set: ju.Set[AnyRef] = nullSet - - assert(set == null) - } - - @Test def testMapWrapping(): Unit = { - val nullMap: mutable.Map[AnyRef, AnyRef] = null - val map: ju.Map[AnyRef, AnyRef] = nullMap - - assert(map == null) - } - - @Test def testConcurrentMapWrapping(): Unit = { - val nullConMap: concurrent.Map[AnyRef, AnyRef] = null - val conMap: juc.ConcurrentMap[AnyRef, AnyRef] = nullConMap - - assert(conMap == null) - } - - @Test def testDictionaryWrapping(): Unit = { - val nullDict: mutable.Map[AnyRef, AnyRef] = null - val dict: ju.Dictionary[AnyRef, AnyRef] = nullDict - - assert(dict == null) - } - - // Implicit conversion to ju.Properties is not available - - @Test def testIteratorDecoration(): Unit = { - val nullIterator: Iterator[AnyRef] = null - - assert(nullIterator.asJava == null) - } - - @Test def testEnumerationDecoration(): Unit = { - val nullEnumeration: Iterator[AnyRef] = null - - assert(nullEnumeration.asJavaEnumeration == null) - } - - @Test def testIterableDecoration(): Unit = { - val nullIterable: Iterable[AnyRef] = null - - assert(nullIterable.asJava == null) - } - - @Test def testCollectionDecoration(): Unit = { - val nullCollection: Iterable[AnyRef] = null - - assert(nullCollection.asJavaCollection == null) - } - - @Test def testBufferDecoration(): Unit = { - val nullBuffer: mutable.Buffer[AnyRef] = null - - assert(nullBuffer.asJava == null) - } - - @Test def testSetDecoration(): Unit = { - val nullSet: Set[AnyRef] = null - - assert(nullSet.asJava == null) - } - - @Test def testMapDecoration(): Unit = { - val nullMap: mutable.Map[AnyRef, AnyRef] = null - - assert(nullMap.asJava == null) - } - - @Test def testConcurrentMapDecoration(): Unit = { - val nullConMap: concurrent.Map[AnyRef, AnyRef] = null - - assert(nullConMap.asJava == null) - } - - @Test def testDictionaryDecoration(): Unit = { - val nullDict: mutable.Map[AnyRef, AnyRef] = null - - assert(nullDict.asJavaDictionary == null) - } - - // Decorator conversion to ju.Properties is not available - } -} diff --git a/test/junit/scala/collection/convert/NullSafetyToJavaTest.scala b/test/junit/scala/collection/convert/NullSafetyToJavaTest.scala new file mode 100644 index 000000000000..da0513ed8ae7 --- /dev/null +++ b/test/junit/scala/collection/convert/NullSafetyToJavaTest.scala @@ -0,0 +1,138 @@ +package scala.collection.convert + +import java.util.{concurrent => juc} +import java.{lang => jl, util => ju} + +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.collection.JavaConverters._ +import scala.collection.convert.ImplicitConversions._ +import scala.collection.{concurrent, mutable} + +// SI-9113: tests to insure that wrappers return null instead of wrapping it as a collection + +@RunWith(classOf[JUnit4]) +class NullSafetyToJavaTest { + @Test def testIteratorWrapping(): Unit = { + val nullIterator: Iterator[AnyRef] = null + val jIterator: ju.Iterator[AnyRef] = nullIterator + + assert(jIterator == null) + } + + @Test def testEnumerationWrapping(): Unit = { + val nullEnumeration: Iterator[AnyRef] = null + val enumeration: ju.Iterator[AnyRef] = nullEnumeration + + assert(enumeration == null) + } + + @Test def testIterableWrapping(): Unit = { + val nullIterable: Iterable[AnyRef] = null + val iterable: jl.Iterable[AnyRef] = asJavaIterable(nullIterable) + + assert(iterable == null) + } + + @Test def testCollectionWrapping(): Unit = { + val nullCollection: Iterable[AnyRef] = null + val collection: ju.Collection[AnyRef] = nullCollection + + assert(collection == null) + } + + @Test def testBufferWrapping(): Unit = { + val nullList: mutable.Buffer[AnyRef] = null + val buffer: ju.List[AnyRef] = nullList + + assert(buffer == null) + } + + @Test def testSetWrapping(): Unit = { + val nullSet: mutable.Set[AnyRef] = null + val set: ju.Set[AnyRef] = nullSet + + assert(set == null) + } + + @Test def testMapWrapping(): Unit = { + val nullMap: mutable.Map[AnyRef, AnyRef] = null + val map: ju.Map[AnyRef, AnyRef] = nullMap + + assert(map == null) + } + + @Test def testConcurrentMapWrapping(): Unit = { + val nullConMap: concurrent.Map[AnyRef, AnyRef] = null + val conMap: juc.ConcurrentMap[AnyRef, AnyRef] = nullConMap + + assert(conMap == null) + } + + @Test def testDictionaryWrapping(): Unit = { + val nullDict: mutable.Map[AnyRef, AnyRef] = null + val dict: ju.Dictionary[AnyRef, AnyRef] = nullDict + + assert(dict == null) + } + + // Implicit conversion to ju.Properties is not available + + @Test def testIteratorDecoration(): Unit = { + val nullIterator: Iterator[AnyRef] = null + + assert(nullIterator.asJava == null) + } + + @Test def testEnumerationDecoration(): Unit = { + val nullEnumeration: Iterator[AnyRef] = null + + assert(nullEnumeration.asJavaEnumeration == null) + } + + @Test def testIterableDecoration(): Unit = { + val nullIterable: Iterable[AnyRef] = null + + assert(nullIterable.asJava == null) + } + + @Test def testCollectionDecoration(): Unit = { + val nullCollection: Iterable[AnyRef] = null + + assert(nullCollection.asJavaCollection == null) + } + + @Test def testBufferDecoration(): Unit = { + val nullBuffer: mutable.Buffer[AnyRef] = null + + assert(nullBuffer.asJava == null) + } + + @Test def testSetDecoration(): Unit = { + val nullSet: Set[AnyRef] = null + + assert(nullSet.asJava == null) + } + + @Test def testMapDecoration(): Unit = { + val nullMap: mutable.Map[AnyRef, AnyRef] = null + + assert(nullMap.asJava == null) + } + + @Test def testConcurrentMapDecoration(): Unit = { + val nullConMap: concurrent.Map[AnyRef, AnyRef] = null + + assert(nullConMap.asJava == null) + } + + @Test def testDictionaryDecoration(): Unit = { + val nullDict: mutable.Map[AnyRef, AnyRef] = null + + assert(nullDict.asJavaDictionary == null) + } + + // Decorator conversion to ju.Properties is not available +} diff --git a/test/junit/scala/collection/convert/NullSafetyToScalaTest.scala b/test/junit/scala/collection/convert/NullSafetyToScalaTest.scala new file mode 100644 index 000000000000..9b6d366fafcf --- /dev/null +++ b/test/junit/scala/collection/convert/NullSafetyToScalaTest.scala @@ -0,0 +1,148 @@ +package scala.collection.convert + +import java.util.{concurrent => juc} +import java.{lang => jl, util => ju} + +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.collection.JavaConverters._ +import scala.collection.convert.ImplicitConversions._ +import scala.collection.{concurrent, mutable} + +// SI-9113: tests to insure that wrappers return null instead of wrapping it as a collection + +@RunWith(classOf[JUnit4]) +class NullSafetyToScalaTest { + @Test def testIteratorWrapping(): Unit = { + val nullJIterator: ju.Iterator[AnyRef] = null + val iterator: Iterator[AnyRef] = nullJIterator + + assert(iterator == null) + } + + @Test def testEnumerationWrapping(): Unit = { + val nullJEnumeration: ju.Enumeration[AnyRef] = null + val enumeration: Iterator[AnyRef] = nullJEnumeration + + assert(enumeration == null) + } + + @Test def testIterableWrapping(): Unit = { + val nullJIterable: jl.Iterable[AnyRef] = null + val iterable: Iterable[AnyRef] = nullJIterable + + assert(iterable == null) + } + + @Test def testCollectionWrapping(): Unit = { + val nullJCollection: ju.Collection[AnyRef] = null + val collection: Iterable[AnyRef] = nullJCollection + + assert(collection == null) + } + + @Test def testBufferWrapping(): Unit = { + val nullJList: ju.List[AnyRef] = null + val buffer: mutable.Buffer[AnyRef] = nullJList + + assert(buffer == null) + } + + @Test def testSetWrapping(): Unit = { + val nullJSet: ju.Set[AnyRef] = null + val set: mutable.Set[AnyRef] = nullJSet + + assert(set == null) + } + + @Test def testMapWrapping(): Unit = { + val nullJMap: ju.Map[AnyRef, AnyRef] = null + val map: mutable.Map[AnyRef, AnyRef] = nullJMap + + assert(map == null) + } + + @Test def testConcurrentMapWrapping(): Unit = { + val nullJConMap: juc.ConcurrentMap[AnyRef, AnyRef] = null + val conMap: concurrent.Map[AnyRef, AnyRef] = nullJConMap + + assert(conMap == null) + } + + @Test def testDictionaryWrapping(): Unit = { + val nullJDict: ju.Dictionary[AnyRef, AnyRef] = null + val dict: mutable.Map[AnyRef, AnyRef] = nullJDict + + assert(dict == null) + } + + + @Test def testPropertyWrapping(): Unit = { + val nullJProps: ju.Properties = null + val props: mutable.Map[String, String] = nullJProps + + assert(props == null) + } + + @Test def testIteratorDecoration(): Unit = { + val nullJIterator: ju.Iterator[AnyRef] = null + + assert(nullJIterator.asScala == null) + } + + @Test def testEnumerationDecoration(): Unit = { + val nullJEnumeration: ju.Enumeration[AnyRef] = null + + assert(nullJEnumeration.asScala == null) + } + + @Test def testIterableDecoration(): Unit = { + val nullJIterable: jl.Iterable[AnyRef] = null + + assert(nullJIterable.asScala == null) + } + + @Test def testCollectionDecoration(): Unit = { + val nullJCollection: ju.Collection[AnyRef] = null + + assert(nullJCollection.asScala == null) + } + + @Test def testBufferDecoration(): Unit = { + val nullJBuffer: ju.List[AnyRef] = null + + assert(nullJBuffer.asScala == null) + } + + @Test def testSetDecoration(): Unit = { + val nullJSet: ju.Set[AnyRef] = null + + assert(nullJSet.asScala == null) + } + + @Test def testMapDecoration(): Unit = { + val nullJMap: ju.Map[AnyRef, AnyRef] = null + + assert(nullJMap.asScala == null) + } + + @Test def testConcurrentMapDecoration(): Unit = { + val nullJConMap: juc.ConcurrentMap[AnyRef, AnyRef] = null + + assert(nullJConMap.asScala == null) + } + + @Test def testDictionaryDecoration(): Unit = { + val nullJDict: ju.Dictionary[AnyRef, AnyRef] = null + + assert(nullJDict.asScala == null) + } + + @Test def testPropertiesDecoration(): Unit = { + val nullJProperties: ju.Properties = null + + assert(nullJProperties.asScala == null) + } +} From eeef2602dc97f84c798713d7a2c924ea2b0d6012 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 30 Jan 2016 21:53:27 -0800 Subject: [PATCH 042/153] SI-8044 Allow binding backquoted varid in patterns Previously, a varid could not be backquoted, so that it was not possible to introduce variables with names such as `type` in a match expression. This commit allows backquoted varids in `case x @ _` and `case x: Int`. In neither position is a stable id accepted, that is, an id with leading uppercase. Therefore, this commit merely relaxes the backquoted varid to be taken as a normal varid in these contexts. --- spec/01-lexical-syntax.md | 2 ++ spec/08-pattern-matching.md | 4 ++-- .../scala/tools/nsc/ast/parser/Parsers.scala | 15 ++++++++------- test/files/neg/t8044.check | 4 ++++ test/files/neg/t8044.scala | 4 ++++ test/files/pos/t8044.scala | 7 +++++++ 6 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 test/files/neg/t8044.check create mode 100644 test/files/neg/t8044.scala create mode 100644 test/files/pos/t8044.scala diff --git a/spec/01-lexical-syntax.md b/spec/01-lexical-syntax.md index 0232ed9a3411..4e92c7cf7b48 100644 --- a/spec/01-lexical-syntax.md +++ b/spec/01-lexical-syntax.md @@ -49,6 +49,8 @@ classes (Unicode general category given in parentheses): ```ebnf op ::= opchar {opchar} varid ::= lower idrest +boundvarid ::= varid + | ‘`’ varid ‘`’ plainid ::= upper idrest | varid | op diff --git a/spec/08-pattern-matching.md b/spec/08-pattern-matching.md index 3b481eea86c3..6753fa3ec783 100644 --- a/spec/08-pattern-matching.md +++ b/spec/08-pattern-matching.md @@ -10,10 +10,10 @@ chapter: 8 ```ebnf Pattern ::= Pattern1 { ‘|’ Pattern1 } - Pattern1 ::= varid ‘:’ TypePat + Pattern1 ::= boundvarid ‘:’ TypePat | ‘_’ ‘:’ TypePat | Pattern2 - Pattern2 ::= varid [‘@’ Pattern3] + Pattern2 ::= boundvarid [‘@’ Pattern3] | Pattern3 Pattern3 ::= SimplePattern | SimplePattern {id [nl] SimplePattern} diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 9c0174d89b99..1e239f91a63f 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1901,19 +1901,20 @@ self => } /** {{{ - * Pattern1 ::= varid `:' TypePat + * Pattern1 ::= boundvarid `:' TypePat * | `_' `:' TypePat * | Pattern2 - * SeqPattern1 ::= varid `:' TypePat + * SeqPattern1 ::= boundvarid `:' TypePat * | `_' `:' TypePat * | [SeqPattern2] * }}} */ def pattern1(): Tree = pattern2() match { case p @ Ident(name) if in.token == COLON => - if (treeInfo.isVarPattern(p)) + if (nme.isVariableName(name)) { + p.removeAttachment[BackquotedIdentifierAttachment.type] atPos(p.pos.start, in.skipToken())(Typed(p, compoundType())) - else { + } else { syntaxError(in.offset, "Pattern variables must start with a lower-case letter. (SLS 8.1.1.)") p } @@ -1921,9 +1922,9 @@ self => } /** {{{ - * Pattern2 ::= varid [ @ Pattern3 ] + * Pattern2 ::= boundvarid [ @ Pattern3 ] * | Pattern3 - * SeqPattern2 ::= varid [ @ SeqPattern3 ] + * SeqPattern2 ::= boundvarid [ @ SeqPattern3 ] * | SeqPattern3 * }}} */ @@ -1935,7 +1936,7 @@ self => case Ident(nme.WILDCARD) => in.nextToken() pattern3() - case Ident(name) if treeInfo.isVarPattern(p) => + case Ident(name) if nme.isVariableName(name) => in.nextToken() atPos(p.pos.start) { Bind(name, pattern3()) } case _ => p diff --git a/test/files/neg/t8044.check b/test/files/neg/t8044.check new file mode 100644 index 000000000000..678bf8c7007b --- /dev/null +++ b/test/files/neg/t8044.check @@ -0,0 +1,4 @@ +t8044.scala:3: error: not found: value _ + def f = 42 match { case `_` : Int => `_` } // doesn't leak quoted underscore + ^ +one error found diff --git a/test/files/neg/t8044.scala b/test/files/neg/t8044.scala new file mode 100644 index 000000000000..930c30c5a5a0 --- /dev/null +++ b/test/files/neg/t8044.scala @@ -0,0 +1,4 @@ + +trait T { + def f = 42 match { case `_` : Int => `_` } // doesn't leak quoted underscore +} diff --git a/test/files/pos/t8044.scala b/test/files/pos/t8044.scala new file mode 100644 index 000000000000..8259f06a8a0e --- /dev/null +++ b/test/files/pos/t8044.scala @@ -0,0 +1,7 @@ + +trait T { + def f = 42 match { case `x` @ _ => x } + def g = 42 match { case `type` @ _ => `type` } + def h = 42 match { case `type` : Int => `type` } + def i = (null: Any) match { case _: Int | _: String => 17 } +} From 2eb1cc2e3df1627cde35afa1237cb10f508fe2f2 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 30 Jan 2016 22:15:34 -0800 Subject: [PATCH 043/153] SI-8044 Test for quoted not-a-varid --- test/files/neg/t8044-b.check | 4 ++++ test/files/neg/t8044-b.scala | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 test/files/neg/t8044-b.check create mode 100644 test/files/neg/t8044-b.scala diff --git a/test/files/neg/t8044-b.check b/test/files/neg/t8044-b.check new file mode 100644 index 000000000000..4a93e9a77238 --- /dev/null +++ b/test/files/neg/t8044-b.check @@ -0,0 +1,4 @@ +t8044-b.scala:3: error: Pattern variables must start with a lower-case letter. (SLS 8.1.1.) + def g = 42 match { case `Oops` : Int => } // must be varish + ^ +one error found diff --git a/test/files/neg/t8044-b.scala b/test/files/neg/t8044-b.scala new file mode 100644 index 000000000000..fb2e921ac95e --- /dev/null +++ b/test/files/neg/t8044-b.scala @@ -0,0 +1,4 @@ + +trait T { + def g = 42 match { case `Oops` : Int => } // must be varish +} From 1e565d879360709758950332c19a77fffee073d1 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 15 Mar 2016 13:24:55 -0700 Subject: [PATCH 044/153] SI-8044 Allow any id in explicit pattern binding Allows arbitrary identifier in `X @ pat`, including non-varids. This goes to regularity. Users of this syntax are not likely to be confused by the "backquoted var id is stable" rule. Also for sequence pattern, `X @ _*`. --- spec/08-pattern-matching.md | 4 ++-- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 7 +++---- test/files/pos/t8044.scala | 8 ++++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/spec/08-pattern-matching.md b/spec/08-pattern-matching.md index 6753fa3ec783..35eb97b948a0 100644 --- a/spec/08-pattern-matching.md +++ b/spec/08-pattern-matching.md @@ -13,7 +13,7 @@ chapter: 8 Pattern1 ::= boundvarid ‘:’ TypePat | ‘_’ ‘:’ TypePat | Pattern2 - Pattern2 ::= boundvarid [‘@’ Pattern3] + Pattern2 ::= id [‘@’ Pattern3] | Pattern3 Pattern3 ::= SimplePattern | SimplePattern {id [nl] SimplePattern} @@ -22,7 +22,7 @@ chapter: 8 | Literal | StableId | StableId ‘(’ [Patterns] ‘)’ - | StableId ‘(’ [Patterns ‘,’] [varid ‘@’] ‘_’ ‘*’ ‘)’ + | StableId ‘(’ [Patterns ‘,’] [id ‘@’] ‘_’ ‘*’ ‘)’ | ‘(’ [Patterns] ‘)’ | XmlPattern Patterns ::= Pattern {‘,’ Patterns} diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 1e239f91a63f..abfb6ae67928 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1922,10 +1922,9 @@ self => } /** {{{ - * Pattern2 ::= boundvarid [ @ Pattern3 ] + * Pattern2 ::= id @ Pattern3 + * | `_' @ Pattern3 * | Pattern3 - * SeqPattern2 ::= boundvarid [ @ SeqPattern3 ] - * | SeqPattern3 * }}} */ def pattern2(): Tree = { @@ -1936,7 +1935,7 @@ self => case Ident(nme.WILDCARD) => in.nextToken() pattern3() - case Ident(name) if nme.isVariableName(name) => + case Ident(name) => in.nextToken() atPos(p.pos.start) { Bind(name, pattern3()) } case _ => p diff --git a/test/files/pos/t8044.scala b/test/files/pos/t8044.scala index 8259f06a8a0e..2519a8306b26 100644 --- a/test/files/pos/t8044.scala +++ b/test/files/pos/t8044.scala @@ -4,4 +4,12 @@ trait T { def g = 42 match { case `type` @ _ => `type` } def h = 42 match { case `type` : Int => `type` } def i = (null: Any) match { case _: Int | _: String => 17 } + + // arbitrary idents allowed in @ syntax + def j = "Fred" match { case Name @ (_: String) => Name } + def k = "Fred" match { case * @ (_: String) => * } + + // also in sequence pattern + def m = List(1,2,3,4,5) match { case List(1, `Rest of them` @ _*) => `Rest of them` } + } From 99dad60d984d3f72338f3bad4c4fe905090edd51 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 25 Feb 2016 13:41:20 -0800 Subject: [PATCH 045/153] SI-7898 Read user input during REPL warmup The compiler is created on main thread and user input is read on an aux thread (opposite to currently). Fixes completion when `-i` is supplied. Now `-i` means pasted and new option `-I` means line-by-line. The temporary reader uses postInit to swap in the underlying reader. Completion is disabled for the temporary reader, rather than blocking while it waits for a compiler. But manically hitting tab is one way of knowing exactly when completion is live. --- .../tools/nsc/GenericRunnerCommand.scala | 1 + .../tools/nsc/GenericRunnerSettings.scala | 8 +- .../scala/tools/nsc/interpreter/ILoop.scala | 165 ++++++++++++------ .../nsc/interpreter/InteractiveReader.scala | 95 ++++++++++ test/files/run/t7805-repl-i.check | 3 - 5 files changed, 212 insertions(+), 60 deletions(-) diff --git a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala index 24496fa013d4..bab612bad5ef 100644 --- a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala +++ b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala @@ -79,6 +79,7 @@ Other startup options: -howtorun what to run (default: guess) -i preload before starting the repl + -I preload , enforcing line-by-line interpretation -e execute as if entered in the repl -save save the compiled script in a jar for future use -nc no compilation daemon: do not use the fsc offline compiler diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala index 1289d55c3726..d1f8db048bad 100644 --- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala +++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala @@ -20,10 +20,16 @@ class GenericRunnerSettings(error: String => Unit) extends Settings(error) { "guess") val loadfiles = + MultiStringSetting( + "-I", + "file", + "load a file line-by-line") + + val pastefiles = MultiStringSetting( "-i", "file", - "load a file (assumes the code is given interactively)") + "paste a file") val execute = StringSetting( diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index adac438b3765..adaf3a5d252b 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -175,10 +175,19 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) echo("\n" + msg) in.redrawLine() } - protected def echo(msg: String) = { + protected var mum = false + protected def echo(msg: String) = if (!mum) { out println msg out.flush() } + // turn off intp reporter and our echo + def mumly[A](op: =>A): A = + if (isReplDebug) op + else intp beSilentDuring { + val saved = mum + mum = true + try op finally mum = saved + } /** Search the history */ def searchHistory(_cmdline: String) { @@ -408,12 +417,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) * command() for each line of input, and stops when * command() returns false. */ - @tailrec final def loop(): LineResult = { + final def loop(): LineResult = loop(readOneLine()) + + @tailrec final def loop(line: String): LineResult = { import LineResults._ - readOneLine() match { - case null => EOF - case line => if (try processLine(line) catch crashRecovery) loop() else ERR - } + if (line == null) EOF + else if (try processLine(line) catch crashRecovery) loop(readOneLine()) + else ERR } /** interpret all lines from a specified file */ @@ -829,19 +839,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } - // runs :load `file` on any files passed via -i - def loadFiles(settings: Settings) = settings match { - case settings: GenericRunnerSettings => - for (filename <- settings.loadfiles.value) { - val cmd = ":load " + filename - command(cmd) - addReplay(cmd) - echo("") - } - case _ => - } - - /** Tries to create a JLineReader, falling back to SimpleReader, + /** Tries to create a jline.InteractiveReader, falling back to SimpleReader, * unless settings or properties are such that it should start with SimpleReader. * The constructor of the InteractiveReader must take a Completion strategy, * supplied as a `() => Completion`; the Completion object provides a concrete Completer. @@ -885,49 +883,104 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } - private def loopPostInit() { - // Bind intp somewhere out of the regular namespace where - // we can get at it in generated code. - intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain])) - // Auto-run code via some setting. - ( replProps.replAutorunCode.option - flatMap (f => io.File(f).safeSlurp()) - foreach (intp quietRun _) - ) - // classloader and power mode setup - intp.setContextClassLoader() - if (isReplPower) { - replProps.power setValue true - unleashAndSetPhase() - asyncMessage(power.banner) - } - // SI-7418 Now, and only now, can we enable TAB completion. - in.postInit() - } - - // start an interpreter with the given settings + /** Start an interpreter with the given settings. + * @return true if successful + */ def process(settings: Settings): Boolean = savingContextLoader { - this.settings = settings - createInterpreter() - // sets in to some kind of reader depending on environmental cues - in = in0.fold(chooseReader(settings))(r => SimpleReader(r, out, interactive = true)) - globalFuture = future { - intp.initializeSynchronous() - loopPostInit() - !intp.reporter.hasErrors + def newReader = in0.fold(chooseReader(settings))(r => SimpleReader(r, out, interactive = true)) + + /** Reader to use before interpreter is online. */ + def preLoop = { + val sr = SplashReader(newReader) { r => + in = r + in.postInit() + } + in = sr + SplashLoop(sr, prompt) } - loadFiles(settings) - printWelcome() - try loop() match { - case LineResults.EOF => out print Properties.shellInterruptedString - case _ => + /* Actions to cram in parallel while collecting first user input at prompt. + * Run with output muted both from ILoop and from the intp reporter. + */ + def loopPostInit(): Unit = mumly { + // Bind intp somewhere out of the regular namespace where + // we can get at it in generated code. + intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain])) + + // add a help function for anyone who types "help" instead of ":help". Easily shadowed. + //addHelp() + + // Auto-run code via some setting. + ( replProps.replAutorunCode.option + flatMap (f => File(f).safeSlurp()) + foreach (intp quietRun _) + ) + // power mode setup + if (isReplPower) { + replProps.power setValue true + unleashAndSetPhase() + asyncMessage(power.banner) + } + loadInitFiles() + // SI-7418 Now, and only now, can we enable TAB completion. + in.postInit() + } + def loadInitFiles(): Unit = settings match { + case settings: GenericRunnerSettings => + for (f <- settings.loadfiles.value) { + loadCommand(f) + addReplay(s":load $f") + } + for (f <- settings.pastefiles.value) { + pasteCommand(f) + addReplay(s":paste $f") + } + case _ => + } + // TODO: wait until after startup to enable obnoxious settings + def withSuppressedSettings[A](body: =>A): A = { + body } - catch AbstractOrMissingHandler() - finally closeInterpreter() + def startup(): String = withSuppressedSettings { + // starting + printWelcome() - true + // let them start typing + val splash = preLoop + splash.start() + + // while we go fire up the REPL + try { + createInterpreter() + intp.initializeSynchronous() + globalFuture = Future successful true + if (intp.reporter.hasErrors) { + echo("Interpreter encountered errors during initialization!") + null + } else { + loopPostInit() + val line = splash.line // what they typed in while they were waiting + if (line == null) { // they ^D + try out print Properties.shellInterruptedString + finally closeInterpreter() + } + line + } + } finally splash.stop() + } + this.settings = settings + startup() match { + case null => false + case line => + try loop(line) match { + case LineResults.EOF => out print Properties.shellInterruptedString + case _ => + } + catch AbstractOrMissingHandler() + finally closeInterpreter() + true + } } @deprecated("Use `process` instead", "2.9.0") diff --git a/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala index 71753a3e3924..1f81d9965c67 100644 --- a/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala +++ b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala @@ -50,3 +50,98 @@ object InteractiveReader { def createDefault(): InteractiveReader = apply() // used by sbt } +/** Collect one line of user input from the supplied reader. + * Runs on a new thread while the REPL is initializing on the main thread. + * + * The user can enter text or a `:paste` command. + */ +class SplashLoop(reader: InteractiveReader, prompt: String) extends Runnable { + import java.util.concurrent.SynchronousQueue + import scala.compat.Platform.EOL + + private val result = new SynchronousQueue[Option[String]] + @volatile private var running: Boolean = _ + private var thread: Thread = _ + + /** Read one line of input which can be retrieved with `line`. */ + def run(): Unit = { + var line = "" + try + do { + line = reader.readLine(prompt) + if (line != null) { + line = process(line.trim) + } + } while (line != null && line.isEmpty && running) + finally { + result.put(Option(line)) + } + } + + /** Check for `:paste` command. */ + private def process(line: String): String = { + def isPrefix(s: String, p: String, n: Int) = ( + //s != null && p.inits.takeWhile(_.length >= n).exists(s == _) + s != null && s.length >= n && s.length <= p.length && s == p.take(s.length) + ) + if (isPrefix(line, ":paste", 3)) { + // while collecting lines, check running flag + var help = f"// Entering paste mode (ctrl-D to finish)%n%n" + def readWhile(cond: String => Boolean) = { + Iterator continually reader.readLine(help) takeWhile { x => + help = "" + x != null && cond(x) + } + } + val text = (readWhile(_ => running) mkString EOL).trim + val next = + if (text.isEmpty) "// Nothing pasted, nothing gained." + else "// Exiting paste mode, now interpreting." + Console println f"%n${next}%n" + text + } else { + line + } + } + + def start(): Unit = result.synchronized { + require(thread == null, "Already started") + thread = new Thread(this) + running = true + thread.start() + } + + def stop(): Unit = result.synchronized { + running = false + if (thread != null) thread.interrupt() + thread = null + } + + /** Block for the result line, or null on ctl-D. */ + def line: String = result.take getOrElse null +} +object SplashLoop { + def apply(reader: SplashReader, prompt: String): SplashLoop = new SplashLoop(reader, prompt) +} + +/** Reader during splash. Handles splash-completion with a stub, otherwise delegates. */ +class SplashReader(reader: InteractiveReader, postIniter: InteractiveReader => Unit) extends InteractiveReader { + /** Invoke the postInit action with the underlying reader. */ + override def postInit(): Unit = postIniter(reader) + + override val interactive: Boolean = reader.interactive + + override def reset(): Unit = reader.reset() + override def history: History = reader.history + override val completion: Completion = NoCompletion + override def redrawLine(): Unit = reader.redrawLine() + + override protected[interpreter] def readOneLine(prompt: String): String = ??? // unused + override protected[interpreter] def readOneKey(prompt: String): Int = ??? // unused + + override def readLine(prompt: String): String = reader.readLine(prompt) +} +object SplashReader { + def apply(reader: InteractiveReader)(postIniter: InteractiveReader => Unit) = + new SplashReader(reader, postIniter) +} diff --git a/test/files/run/t7805-repl-i.check b/test/files/run/t7805-repl-i.check index 24512c006733..70f024605caa 100644 --- a/test/files/run/t7805-repl-i.check +++ b/test/files/run/t7805-repl-i.check @@ -1,6 +1,3 @@ -Loading t7805-repl-i.script... -import util._ - Welcome to Scala Type in expressions for evaluation. Or try :help. From c89c36597f922fe29cbb3cec8095611f86ba4976 Mon Sep 17 00:00:00 2001 From: Martijn Hoekstra Date: Mon, 16 May 2016 18:52:06 +0200 Subject: [PATCH 046/153] SI-9766 - allow ++ on empty ConcatIterator --- src/library/scala/collection/Iterator.scala | 3 ++- test/junit/scala/collection/IteratorTest.scala | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 8d88b1c6b14f..9ba16976bd49 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -200,7 +200,8 @@ object Iterator { } else Iterator.empty.next() override def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = - new ConcatIterator(current, queue :+ (() => that.toIterator)) + if(current eq null) new JoinIterator(Iterator.empty, that) + else new ConcatIterator(current, queue :+ (() => that.toIterator)) } private[scala] final class JoinIterator[+A](lhs: Iterator[A], that: => GenTraversableOnce[A]) extends Iterator[A] { diff --git a/test/junit/scala/collection/IteratorTest.scala b/test/junit/scala/collection/IteratorTest.scala index 329c85127a5d..d980cadeb3c4 100644 --- a/test/junit/scala/collection/IteratorTest.scala +++ b/test/junit/scala/collection/IteratorTest.scala @@ -192,4 +192,22 @@ class IteratorTest { assertSameElements(exp, res) assertEquals(8, counter) // was 14 } + + // SI-9766 + @Test def exhaustedConcatIteratorConcat: Unit = { + def consume[A](i: Iterator[A]) = { + while(i.hasNext) i.next() + } + val joiniter = Iterator.empty ++ Seq(1, 2, 3) + assertTrue(joiniter.hasNext) + consume(joiniter) + val concatiter = joiniter ++ Seq(4, 5, 6) + assertTrue(concatiter.hasNext) + consume(concatiter) + assertFalse(concatiter.hasNext) + val concatFromEmpty = concatiter ++ Seq(7, 8, 9) + assertTrue(concatFromEmpty.hasNext) + consume(concatFromEmpty) + assertFalse(concatFromEmpty.hasNext) + } } From a412ea04ba0ba41dbac469b89e1412f0c56fce3f Mon Sep 17 00:00:00 2001 From: Raphael Jolly Date: Tue, 9 Feb 2016 22:16:22 +0100 Subject: [PATCH 047/153] Use jarlister in build The goal of this change is to exercize the "manifest classpath" mechanism, meant to bring the compiler its needed classes as resources, listed in jar manifests, as opposed to files, thus enabling to use the compiler in sandboxed environments (and also the scripting engine for that matter). --- build.xml | 14 +++++++++++++- test/files/run/t7843-jsr223-service.scala | 6 ++---- test/files/run/t7933.scala | 6 ++---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/build.xml b/build.xml index 7b49544447c7..e0b2f353e107 100644 --- a/build.xml +++ b/build.xml @@ -279,6 +279,10 @@ TODO: + + + + @@ -867,6 +871,11 @@ TODO: + + + + + @@ -1230,7 +1239,10 @@ TODO: - + + + + diff --git a/test/files/run/t7843-jsr223-service.scala b/test/files/run/t7843-jsr223-service.scala index 31112212eaf4..3c853878ba3b 100644 --- a/test/files/run/t7843-jsr223-service.scala +++ b/test/files/run/t7843-jsr223-service.scala @@ -1,8 +1,6 @@ -import scala.tools.nsc.interpreter.IMain - object Test extends App { - val engine = new IMain.Factory getScriptEngine() - engine.asInstanceOf[IMain].settings.usejavacp.value = true + val m = new javax.script.ScriptEngineManager() + val engine = m.getEngineByName("scala") engine put ("n", 10) engine eval "1 to n.asInstanceOf[Int] foreach print" } diff --git a/test/files/run/t7933.scala b/test/files/run/t7933.scala index b06dffcd80a9..58e39dd3843a 100644 --- a/test/files/run/t7933.scala +++ b/test/files/run/t7933.scala @@ -1,8 +1,6 @@ -import scala.tools.nsc.interpreter.IMain - object Test extends App { - val engine = new IMain.Factory getScriptEngine() - engine.asInstanceOf[IMain].settings.usejavacp.value = true + val m = new javax.script.ScriptEngineManager() + val engine = m.getEngineByName("scala") val res2 = engine.asInstanceOf[javax.script.Compilable] res2 compile "8" eval() val res5 = res2 compile """println("hello") ; 8""" From 206a657225f16c0fa847f0b2abaddc17b8d945d7 Mon Sep 17 00:00:00 2001 From: Raphael Jolly Date: Fri, 20 May 2016 20:09:53 +0200 Subject: [PATCH 048/153] Jarlist scala-library in build.sbt --- build.sbt | 5 ++++- project/Osgi.scala | 13 +++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 984ac0e91cc6..da86f6274b79 100644 --- a/build.sbt +++ b/build.sbt @@ -351,6 +351,7 @@ lazy val library = configureAsSubproject(project) products in Compile in packageBin ++= (products in Compile in packageBin in forkjoin).value, Osgi.headers += "Import-Package" -> "sun.misc;resolution:=optional, *", + Osgi.jarlist := true, fixPom( "/project/name" -> Scala Library, "/project/description" -> Standard library for the Scala Programming Language, @@ -420,13 +421,15 @@ lazy val compiler = configureAsSubproject(project) scalacOptions in Compile in doc ++= Seq( "-doc-root-content", (sourceDirectory in Compile).value + "/rootdoc.txt" ), - Osgi.headers += + Osgi.headers ++= Seq( "Import-Package" -> ("jline.*;resolution:=optional," + "org.apache.tools.ant.*;resolution:=optional," + "scala.util.parsing.*;version=\"${range;[====,====];"+versionNumber("scala-parser-combinators")+"}\";resolution:=optional," + "scala.xml.*;version=\"${range;[====,====];"+versionNumber("scala-xml")+"}\";resolution:=optional," + "scala.*;version=\"${range;[==,=+);${ver}}\"," + "*"), + "Class-Path" -> "scala-reflect.jar scala-library.jar" + ), // Generate the ScriptEngineFactory service definition. The ant build does this when building // the JAR but sbt has no support for it and it is easier to do as a resource generator: generateServiceProviderResources("javax.script.ScriptEngineFactory" -> "scala.tools.nsc.interpreter.IMain$Factory"), diff --git a/project/Osgi.scala b/project/Osgi.scala index 4456c9419051..d780be2f78ed 100644 --- a/project/Osgi.scala +++ b/project/Osgi.scala @@ -1,6 +1,7 @@ import aQute.lib.osgi.Builder import aQute.lib.osgi.Constants._ import java.util.Properties +import java.util.jar.Attributes import sbt._ import sbt.Keys._ import scala.collection.JavaConversions._ @@ -16,6 +17,7 @@ object Osgi { val bundleName = SettingKey[String]("osgiBundleName", "The Bundle-Name for the manifest.") val bundleSymbolicName = SettingKey[String]("osgiBundleSymbolicName", "The Bundle-SymbolicName for the manifest.") val headers = SettingKey[Seq[(String, String)]]("osgiHeaders", "Headers and processing instructions for BND.") + val jarlist = SettingKey[Boolean]("osgiJarlist", "List classes in manifest.") def settings: Seq[Setting[_]] = Seq( bundleName := description.value, @@ -33,8 +35,9 @@ object Osgi { "-eclipse" -> "false" ) }, + jarlist := false, bundle <<= Def.task { - bundleTask(headers.value.toMap, (products in Compile in packageBin).value, + bundleTask(headers.value.toMap, jarlist.value, (products in Compile in packageBin).value, (artifactPath in (Compile, packageBin)).value, Nil, streams.value) }, packagedArtifact in (Compile, packageBin) <<= (artifact in (Compile, packageBin), bundle).identityMap, @@ -47,7 +50,7 @@ object Osgi { ) ) - def bundleTask(headers: Map[String, String], fullClasspath: Seq[File], artifactPath: File, + def bundleTask(headers: Map[String, String], jarlist: Boolean, fullClasspath: Seq[File], artifactPath: File, resourceDirectories: Seq[File], streams: TaskStreams): File = { val log = streams.log val builder = new Builder @@ -62,6 +65,12 @@ object Osgi { builder.getWarnings.foreach(s => log.warn(s"bnd: $s")) builder.getErrors.foreach(s => log.error(s"bnd: $s")) IO.createDirectory(artifactPath.getParentFile) + if (jarlist) { + val entries = jar.getManifest.getEntries + for ((name, resource) <- jar.getResources if name.endsWith(".class")) { + entries.put(name, new Attributes) + } + } jar.write(artifactPath) artifactPath } From 093c9346dec958c46d0ae2e0473eaca463a5f922 Mon Sep 17 00:00:00 2001 From: chrisokasaki Date: Sun, 22 May 2016 21:54:06 -0400 Subject: [PATCH 049/153] SI-9776: Fix type of PriorityQueue.newBuilder and improve performance - Fix the return type of mutable.PriorityQueue.newBuilder to be Builder[A, PriorityQueue[A]] rather than PriorityQueue[A]. - Improve performance of bulk inserts from O(N log N) to O(N), primarily in the builder, ++=, and reverse. These changes indirectly benefit the many other methods that use the builder or ++=. - Improve performance of clone. - Fix SI-9757 space leak in dequeue. --- .../collection/mutable/PriorityQueue.scala | 124 +++++++++++++++--- .../scalacheck/MutablePriorityQueue.scala | 102 ++++++++++++++ 2 files changed, 208 insertions(+), 18 deletions(-) create mode 100644 test/files/scalacheck/MutablePriorityQueue.scala diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index d5b7673c373c..a6c0fc207791 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -66,7 +66,7 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) def p_swap(a: Int, b: Int) = super.swap(a, b) } - protected[this] override def newBuilder = new PriorityQueue[A] + protected[this] override def newBuilder = PriorityQueue.newBuilder[A] private val resarr = new ResizableArrayAccess[A] @@ -89,14 +89,15 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) } } - protected def fixDown(as: Array[AnyRef], m: Int, n: Int): Unit = { + protected def fixDown(as: Array[AnyRef], m: Int, n: Int): Boolean = { + // returns true if any swaps were done (used in heapify) var k: Int = m while (n >= 2 * k) { var j = 2 * k if (j < n && toA(as(j)) < toA(as(j + 1))) j += 1 if (toA(as(k)) >= toA(as(j))) - return + return k != m else { val h = as(k) as(k) = as(j) @@ -104,6 +105,7 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) k = j } } + k != m } /** Inserts a single element into the priority queue. @@ -119,6 +121,66 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) this } + override def ++=(xs: TraversableOnce[A]): this.type = { + val from = resarr.p_size0 + for (x <- xs) unsafeAdd(x) + heapify(from) + this + } + + private def unsafeAdd(elem: A): Unit = { + // like += but skips fixUp, which breaks the ordering invariant + // a series of unsafeAdds MUST be followed by heapify + resarr.p_ensureSize(resarr.p_size0 + 1) + resarr.p_array(resarr.p_size0) = elem.asInstanceOf[AnyRef] + resarr.p_size0 += 1 + } + + private def heapify(from: Int): Unit = { + // elements at indices 1..from-1 were already in heap order before any adds + // elements at indices from..n are newly added, their order must be fixed + val n = length + + if (from <= 2) { + // no pre-existing order to maintain, do the textbook heapify algorithm + for (i <- n/2 to 1 by -1) fixDown(resarr.p_array, i, n) + } + else if (n - from < 4) { + // for very small adds, doing the simplest fix is faster + for (i <- from to n) fixUp(resarr.p_array, i) + } + else { + var min = from/2 // tracks the minimum element in the queue + val queue = scala.collection.mutable.Queue[Int](min) + + // do fixDown on the parents of all the new elements + // except the parent of the first new element, which is in the queue + // (that parent is treated specially because it might be the root) + for (i <- n/2 until min by -1) { + if (fixDown(resarr.p_array, i, n)) { + // there was a swap, so also need to fixDown i's parent + val parent = i/2 + if (parent < min) { // make sure same parent isn't added twice + min = parent + queue += parent + } + } + } + + while (queue.nonEmpty) { + val i = queue.dequeue() + if (fixDown(resarr.p_array, i, n)) { + val parent = i/2 + if (parent < min && parent > 0) { + // the "parent > 0" is to avoid adding the parent of the root + min = parent + queue += parent + } + } + } + } + } + /** Adds all elements provided by a `TraversableOnce` object * into the priority queue. * @@ -142,9 +204,11 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) def dequeue(): A = if (resarr.p_size0 > 1) { resarr.p_size0 = resarr.p_size0 - 1 - resarr.p_swap(1, resarr.p_size0) + val result = resarr.p_array(1) + resarr.p_array(1) = resarr.p_array(resarr.p_size0) + resarr.p_array(resarr.p_size0) = null // erase reference from array fixDown(resarr.p_array, 1, resarr.p_size0 - 1) - toA(resarr.p_array(resarr.p_size0)) + toA(result) } else throw new NoSuchElementException("no element to remove from heap") @@ -186,25 +250,34 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) } } - /** Returns the reverse of this queue. The priority queue that gets - * returned will have an inversed ordering - if for some elements - * `x` and `y` the original queue's ordering - * had `compare` returning an integer ''w'', the new one will return ''-w'', - * assuming the original ordering abides its contract. + /** Returns the reverse of this priority queue. The new priority queue has + * the same elements as the original, but the opposite ordering. * - * Note that the order of the elements will be reversed unless the - * `compare` method returns 0. In this case, such elements - * will be subsequent, but their corresponding subinterval may be inappropriately - * reversed. However, due to the compare-equals contract, they will also be equal. + * For example, the element with the highest priority in `pq` has the lowest + * priority in `pq.reverse`, and vice versa. * - * @return A reversed priority queue. + * Ties are handled arbitrarily. Elements with equal priority may or + * may not be reversed with respect to each other. + * + * @return the reversed priority queue. */ def reverse = { val revq = new PriorityQueue[A]()(ord.reverse) - for (i <- 1 until resarr.length) revq += resarr(i) + // copy the existing data into the new array backwards + // this won't put it exactly into the correct order, + // but will require less fixing than copying it in + // the original order + val n = resarr.p_size0 + revq.resarr.p_ensureSize(n) + revq.resarr.p_size0 = n + val from = resarr.p_array + val to = revq.resarr.p_array + for (i <- 1 until n) to(i) = from(n-i) + revq.heapify(1) revq } + /** Returns an iterator which yields all the elements in the reverse order * than that returned by the method `iterator`. * @@ -254,12 +327,27 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) * * @return a priority queue with the same elements. */ - override def clone(): PriorityQueue[A] = new PriorityQueue[A] ++= this.iterator + override def clone(): PriorityQueue[A] = { + val pq = new PriorityQueue[A] + val n = resarr.p_size0 + pq.resarr.p_ensureSize(n) + pq.resarr.p_size0 = n + scala.compat.Platform.arraycopy(resarr.p_array, 1, pq.resarr.p_array, 1, n-1) + pq + } } object PriorityQueue extends OrderedTraversableFactory[PriorityQueue] { - def newBuilder[A](implicit ord: Ordering[A]) = new PriorityQueue[A] + def newBuilder[A](implicit ord: Ordering[A]): Builder[A, PriorityQueue[A]] = { + new Builder[A, PriorityQueue[A]] { + val pq = new PriorityQueue[A] + def +=(elem: A): this.type = { pq.unsafeAdd(elem); this } + def result(): PriorityQueue[A] = { pq.heapify(1); pq } + def clear(): Unit = pq.clear() + } + } + implicit def canBuildFrom[A](implicit ord: Ordering[A]): CanBuildFrom[Coll, A, PriorityQueue[A]] = new GenericCanBuildFrom[A] } diff --git a/test/files/scalacheck/MutablePriorityQueue.scala b/test/files/scalacheck/MutablePriorityQueue.scala new file mode 100644 index 000000000000..687e2e7c623b --- /dev/null +++ b/test/files/scalacheck/MutablePriorityQueue.scala @@ -0,0 +1,102 @@ +import scala.collection.mutable.PriorityQueue +import org.scalacheck._ +import Prop._ +import Arbitrary._ + +object Test extends Properties("PriorityQueue") { + type E = Int // the element type used for most/all of the tests + + def checkInvariant[A](pq: PriorityQueue[A])(implicit ord: Ordering[A]): Boolean = { + // The ordering invariant in the heap is that parent >= child. + // A child at index i has a parent at index i/2 in the priority + // queue's internal array. However, that array is padded with + // an extra slot in front so that the first real element is at + // index 1. The vector below is not padded, so subtract 1 from + // every index. + import ord._ + val vec = pq.toVector // elements in same order as pq's internal array + 2 until pq.size forall { i => vec(i/2-1) >= vec(i-1) } + } + + property("newBuilder (in companion)") = forAll { list: List[E] => + val builder = PriorityQueue.newBuilder[E] + for (x <- list) builder += x + val pq = builder.result() + checkInvariant(pq) && + pq.dequeueAll == list.sorted.reverse + } + + property("to[PriorityQueue]") = forAll { list: List[E] => + val pq = list.to[PriorityQueue] + checkInvariant(pq) && + pq.dequeueAll == list.sorted.reverse + } + + property("apply (in companion)") = forAll { list: List[E] => + val pq = PriorityQueue.apply(list : _*) + checkInvariant(pq) && + pq.dequeueAll == list.sorted.reverse + } + + property("size, isEmpty") = forAll { list: List[E] => + val pq = PriorityQueue(list : _*) + pq.size == list.size && pq.isEmpty == list.isEmpty + } + + property("+=") = forAll { (x: E, list: List[E]) => + val pq = PriorityQueue(list : _*) + pq += x + checkInvariant(pq) && + pq.dequeueAll == (x :: list).sorted.reverse + } + + property("++= on empty") = forAll { list: List[E] => + val pq = PriorityQueue.empty[E] + pq ++= list + checkInvariant(pq) && + pq.dequeueAll == list.sorted.reverse + } + + property("++=") = forAll { (list1: List[E], list2: List[E]) => + val pq = PriorityQueue(list1 : _*) + pq ++= list2 + checkInvariant(pq) && + pq.dequeueAll == (list1 ++ list2).sorted.reverse + } + + property("reverse") = forAll { list: List[E] => + val pq = PriorityQueue(list : _*).reverse + checkInvariant(pq)(implicitly[Ordering[E]].reverse) && + pq.dequeueAll == list.sorted + } + + property("reverse then ++=") = forAll { list: List[E] => + val pq = PriorityQueue.empty[E].reverse ++= list + checkInvariant(pq)(implicitly[Ordering[E]].reverse) && + pq.dequeueAll == list.sorted + } + + property("reverse then +=") = forAll { (x: E, list: List[E]) => + val pq = PriorityQueue(list : _*).reverse += x + checkInvariant(pq)(implicitly[Ordering[E]].reverse) && + pq.dequeueAll == (x +: list).sorted + } + + property("clone") = forAll { list: List[E] => + val pq = PriorityQueue(list : _*) + val c = pq.clone() + (pq ne c) && + checkInvariant(c) && + c.dequeueAll == pq.dequeueAll + } + + property("dequeue") = forAll { list: List[E] => + list.nonEmpty ==> { + val pq = PriorityQueue(list : _*) + val x = pq.dequeue() + checkInvariant(pq) && + x == list.max && pq.dequeueAll == list.sorted.reverse.tail + } + } + +} From 869df338617f2210217827c83d3ef9dc6d810e65 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 20 May 2016 18:19:08 -0700 Subject: [PATCH 050/153] SI-7898 Quiet REPL at startup Enable noisy modes only when interpreting user input. --- .../scala/tools/nsc/interpreter/ILoop.scala | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index adaf3a5d252b..4e0f60cf2b68 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -908,9 +908,6 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) // we can get at it in generated code. intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain])) - // add a help function for anyone who types "help" instead of ":help". Easily shadowed. - //addHelp() - // Auto-run code via some setting. ( replProps.replAutorunCode.option flatMap (f => File(f).safeSlurp()) @@ -938,9 +935,24 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } case _ => } - // TODO: wait until after startup to enable obnoxious settings - def withSuppressedSettings[A](body: =>A): A = { - body + // wait until after startup to enable noisy settings + def withSuppressedSettings[A](body: => A): A = { + val ss = this.settings + import ss._ + val noisy = List(Xprint, Ytyperdebug) + val noisesome = noisy.exists(!_.isDefault) + val current = (Xprint.value, Ytyperdebug.value) + if (isReplDebug || !noisesome) body + else { + this.settings.Xprint.value = List.empty + this.settings.Ytyperdebug.value = false + try body + finally { + Xprint.value = current._1 + Ytyperdebug.value = current._2 + intp.global.printTypings = current._2 + } + } } def startup(): String = withSuppressedSettings { // starting From 03d2de20047ad853d80c5c1aae68298082af27d3 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 25 Apr 2016 13:51:02 +0200 Subject: [PATCH 051/153] SI-9121 test case (fixed in new optimizer), SI-9179 test case Also adds a mising phase travel in the backend. A comment already points out why it's necessary, but it was actually forgotten. --- .../tools/nsc/backend/jvm/BCodeHelpers.scala | 2 +- .../tools/nsc/backend/jvm/BytecodeTest.scala | 31 +++++++++++++++++++ .../nsc/backend/jvm/opt/InlinerTest.scala | 23 ++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index a32c21795dbd..a5744983b280 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -76,7 +76,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { val origOwner = sym.originalOwner // phase travel necessary: after flatten, the name includes the name of outer classes. // if some outer name contains $anon, a non-anon class is considered anon. - if (delambdafyInline() && sym.rawowner.isAnonymousFunction) { + if (delambdafyInline() && exitingPickler(sym.rawowner.isAnonymousFunction)) { // SI-9105: special handling for anonymous functions under delambdafy:inline. // // class C { def t = () => { def f { class Z } } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala index 7954fe2360d9..b2ee8b3a4570 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala @@ -1,5 +1,6 @@ package scala.tools.nsc.backend.jvm +import org.junit.Assert._ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -137,4 +138,34 @@ class BytecodeTest extends BytecodeTesting { Label(14), Op(ICONST_0), Label(17), Op(IRETURN))) } + + @Test // wrong local variable table for methods containing while loops + def t9179(): Unit = { + val code = + """class C { + | def t(): Unit = { + | var x = "" + | while (x != null) { + | foo() + | x = null + | } + | bar() + | } + | def foo(): Unit = () + | def bar(): Unit = () + |} + """.stripMargin + val c = compileClass(code) + val t = getMethod(c, "t") + val isFrameLine = (x: Instruction) => x.isInstanceOf[FrameEntry] || x.isInstanceOf[LineNumber] + assertSameCode(t.instructions.filterNot(isFrameLine), List( + Label(0), Ldc(LDC, ""), Label(3), VarOp(ASTORE, 1), + Label(5), VarOp(ALOAD, 1), Jump(IFNULL, Label(21)), + Label(10), VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "C", "foo", "()V", false), Label(14), Op(ACONST_NULL), VarOp(ASTORE, 1), Label(18), Jump(GOTO, Label(5)), + Label(21), VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "C", "bar", "()V", false), Label(26), Op(RETURN), Label(28))) + val labels = t.instructions collect { case l: Label => l } + val x = t.localVars.find(_.name == "x").get + assertEquals(x.start, labels(1)) + assertEquals(x.end, labels(7)) + } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 4e014d452983..fd020c7d9390 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -1503,4 +1503,27 @@ class InlinerTest extends BytecodeTesting { assertNoIndy(t) assertInvoke(t, "C", "C$$$anonfun$1") } + + @Test + def t9121(): Unit = { + val codes = List( + """package p1 + |object Implicits { + | class ScalaObservable(val underlying: Any) extends AnyVal { + | @inline def scMap[R](f: String): Any = f.toRx + | } + | implicit class RichFunction1[T1, R](val f: String) extends AnyVal { + | def toRx: Any = "" + | } + |} + """.stripMargin, + """ + |import p1.Implicits._ + |class C { + | def t(): Unit = new ScalaObservable("").scMap("") + |} + """.stripMargin) + val c :: _ = compileClassesSeparately(codes, extraArgs = compilerArgs) + assertInvoke(getMethod(c, "t"), "p1/Implicits$RichFunction1$", "toRx$extension") + } } From 41965695b71bc00ea60003c39c72a0e10bfd621f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Giero=C5=84?= Date: Mon, 23 May 2016 15:17:24 +0200 Subject: [PATCH 052/153] SI-9688 Make merge in immutable HashMap1 work with null kv. The kv field of scala.collection.immutable.HashMap.HashMap1 can be null. This commit corrects the behavior of updated0 (which is on call path for merged) to work in such cases, instead of throwing NPE. Commit contains regression test. --- .../scala/collection/immutable/HashMap.scala | 2 +- .../collection/immutable/HashMapTest.scala | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/junit/scala/collection/immutable/HashMapTest.scala diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index 92d915fe8b04..3e482f1369d2 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -197,7 +197,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { if (this.value.asInstanceOf[AnyRef] eq value.asInstanceOf[AnyRef]) this else new HashMap1(key, hash, value, kv) } else { - val nkv = merger(this.kv, kv) + val nkv = merger(this.ensurePair, if(kv != null) kv else (key, value)) new HashMap1(nkv._1, hash, nkv._2, nkv) } } else { diff --git a/test/junit/scala/collection/immutable/HashMapTest.scala b/test/junit/scala/collection/immutable/HashMapTest.scala new file mode 100644 index 000000000000..a970786455e4 --- /dev/null +++ b/test/junit/scala/collection/immutable/HashMapTest.scala @@ -0,0 +1,48 @@ +package scala.collection.immutable + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(classOf[JUnit4]) +class HashMapTest { + + private val computeHashF = { + HashMap.empty.computeHash _ + } + + @Test + def canMergeIdenticalHashMap1sWithNullKvs() { + def m = new HashMap.HashMap1(1, computeHashF(1), 1, null) + val merged = m.merged(m)(null) + assertEquals(m, merged) + } + + @Test + def canMergeIdenticalHashMap1sWithNullKvsCustomMerge() { + def m = new HashMap.HashMap1(1, computeHashF(1), 1, null) + val merged = m.merged(m) { + case ((k1, v1), (k2, v2)) => + (k1, v1 + v2) + } + assertEquals(new HashMap.HashMap1(1, computeHashF(1), 2, null), merged) + } + + @Test + def canMergeHashMap1sWithNullKvsHashCollision() { + val key1 = 1000L * 1000 * 1000 * 10 + val key2 = key1.##.toLong + assert(key1.## == key2.##) + + val m1 = new HashMap.HashMap1(key1, computeHashF(key1.##), 1, null) + val m2 = new HashMap.HashMap1(key2, computeHashF(key2.##), 1, null) + val expected = HashMap(key1 -> 1, key2 -> 1) + val merged = m1.merged(m2)(null) + assertEquals(expected, merged) + val mergedWithMergeFunction = m1.merged(m2) { (kv1, kv2) => + throw new RuntimeException("Should not be reached.") + } + assertEquals(expected, mergedWithMergeFunction) + } +} \ No newline at end of file From 90ca3fd6aeddd2aa54537cc940f4b69f2592b447 Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Mon, 23 May 2016 18:58:07 +0100 Subject: [PATCH 053/153] Group Console and AnsiColor entities and add usage examples - Group AnsiColor and Console members - Add Console IO redefinition examples - Add Console control code examples - Add color swatches to AnsiColor - Add AnsiColor control code examples - Link to StdIn for reading - Fix link syntax for java.util.Formatter - Fix withErr method example --- src/library/scala/Console.scala | 146 ++++++++++++++++++++++--- src/library/scala/io/AnsiColor.scala | 155 +++++++++++++++++++++++---- 2 files changed, 265 insertions(+), 36 deletions(-) diff --git a/src/library/scala/Console.scala b/src/library/scala/Console.scala index 37127a93d5ee..0b079aae1590 100644 --- a/src/library/scala/Console.scala +++ b/src/library/scala/Console.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2003-2016, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -12,12 +12,115 @@ import java.io.{ BufferedReader, InputStream, InputStreamReader, OutputStream, P import scala.io.{ AnsiColor, StdIn } import scala.util.DynamicVariable -/** Implements functionality for - * printing Scala values on the terminal as well as reading specific values. +/** Implements functionality for printing Scala values on the terminal. For reading values + * use [[scala.io.StdIn$ StdIn]]. * Also defines constants for marking up text on ANSI terminals. * + * == Console Output == + * + * Use the print methods to output text. + * {{{ + * scala> Console.printf( + * "Today the outside temperature is a balmy %.1f°C. %<.1f°C beats the previous record of %.1f°C.\n", + * -137.0, + * -135.05) + * Today the outside temperature is a balmy -137.0°C. -137.0°C beats the previous record of -135.1°C. + * }}} + * + * == ANSI escape codes == + * Use the ANSI escape codes for colorizing console output either to STDOUT or STDERR. + * {{{ + * import Console.{GREEN, RED, RESET, YELLOW_B, UNDERLINED} + * + * object PrimeTest { + * + * def isPrime(): Unit = { + * + * val candidate = io.StdIn.readInt().ensuring(_ > 1) + * + * val prime = (2 to candidate - 1).forall(candidate % _ != 0) + * + * if (prime) + * Console.println(s"${RESET}${GREEN}yes${RESET}") + * else + * Console.err.println(s"${RESET}${YELLOW_B}${RED}${UNDERLINED}NO!${RESET}") + * } + * + * def main(args: Array[String]): Unit = isPrime() + * + * } + * }}} + * + * + * + * + * + * + * + * + *
$ scala PrimeTest
1234567891
yes
$ scala PrimeTest
56474
NO!
+ * + * == IO redefinition == + * + * Use IO redefinition to temporarily swap in a different set of input and/or output streams. In this example the stream based + * method above is wrapped into a function. + * + * {{{ + * import java.io.{ByteArrayOutputStream, StringReader} + * + * object FunctionalPrimeTest { + * + * def isPrime(candidate: Int): Boolean = { + * + * val input = new StringReader(s"$candidate\n") + * val outCapture = new ByteArrayOutputStream + * val errCapture = new ByteArrayOutputStream + * + * Console.withIn(input) { + * Console.withOut(outCapture) { + * Console.withErr(errCapture) { + * PrimeTest.isPrime() + * } + * } + * } + * + * if (outCapture.toByteArray.nonEmpty) // "yes" + * true + * else if (errCapture.toByteArray.nonEmpty) // "NO!" + * false + * else throw new IllegalArgumentException(candidate.toString) + * } + * + * def main(args: Array[String]): Unit = { + * val primes = (2 to 50) filter (isPrime) + * println(s"First primes: $primes") + * } + * + * } + * }}} + * + * + * + * + * + *
$ scala FunctionalPrimeTest
First primes: Vector(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47)
+ * * @author Matthias Zenger * @version 1.0, 03/09/2003 + * + * @groupname console-output Console Output + * @groupprio console-output 30 + * @groupdesc console-output These methods provide output via the console. + * + * @groupname io-default IO Defaults + * @groupprio io-default 50 + * @groupdesc io-default These values provide direct access to the standard IO channels + * + * @groupname io-redefinition IO Redefinition + * @groupprio io-redefinition 60 + * @groupdesc io-redefinition These methods allow substituting alternative streams for the duration of + * a body of code. Threadsafe by virtue of [[scala.util.DynamicVariable]]. + * */ object Console extends DeprecatedConsole with AnsiColor { private val outVar = new DynamicVariable[PrintStream](java.lang.System.out) @@ -29,11 +132,17 @@ object Console extends DeprecatedConsole with AnsiColor { protected def setErrDirect(err: PrintStream): Unit = errVar.value = err protected def setInDirect(in: BufferedReader): Unit = inVar.value = in - /** The default output, can be overridden by `setOut` */ + /** The default output, can be overridden by `withOut` + * @group io-default + */ def out = outVar.value - /** The default error, can be overridden by `setErr` */ + /** The default error, can be overridden by `withErr` + * @group io-default + */ def err = errVar.value - /** The default input, can be overridden by `setIn` */ + /** The default input, can be overridden by `withIn` + * @group io-default + */ def in = inVar.value /** Sets the default output stream for the duration @@ -48,6 +157,7 @@ object Console extends DeprecatedConsole with AnsiColor { * the new output stream active * @return the results of `thunk` * @see `withOut[T](out:OutputStream)(thunk: => T)` + * @group io-redefinition */ def withOut[T](out: PrintStream)(thunk: =>T): T = outVar.withValue(out)(thunk) @@ -60,6 +170,7 @@ object Console extends DeprecatedConsole with AnsiColor { * the new output stream active * @return the results of `thunk` * @see `withOut[T](out:PrintStream)(thunk: => T)` + * @group io-redefinition */ def withOut[T](out: OutputStream)(thunk: =>T): T = withOut(new PrintStream(out))(thunk) @@ -67,7 +178,7 @@ object Console extends DeprecatedConsole with AnsiColor { /** Set the default error stream for the duration * of execution of one thunk. * @example {{{ - * withErr(Console.out) { println("This goes to default _out_") } + * withErr(Console.out) { err.println("This goes to default _out_") } * }}} * * @param err the new error stream. @@ -75,6 +186,7 @@ object Console extends DeprecatedConsole with AnsiColor { * the new error stream active * @return the results of `thunk` * @see `withErr[T](err:OutputStream)(thunk: =>T)` + * @group io-redefinition */ def withErr[T](err: PrintStream)(thunk: =>T): T = errVar.withValue(err)(thunk) @@ -87,6 +199,7 @@ object Console extends DeprecatedConsole with AnsiColor { * the new error stream active * @return the results of `thunk` * @see `withErr[T](err:PrintStream)(thunk: =>T)` + * @group io-redefinition */ def withErr[T](err: OutputStream)(thunk: =>T): T = withErr(new PrintStream(err))(thunk) @@ -105,8 +218,9 @@ object Console extends DeprecatedConsole with AnsiColor { * @param thunk the code to execute with * the new input stream active * - * @return the results of `thunk` - * @see `withIn[T](in:InputStream)(thunk: =>T)` + * @return the results of `thunk` + * @see `withIn[T](in:InputStream)(thunk: =>T)` + * @group io-redefinition */ def withIn[T](reader: Reader)(thunk: =>T): T = inVar.withValue(new BufferedReader(reader))(thunk) @@ -117,8 +231,9 @@ object Console extends DeprecatedConsole with AnsiColor { * @param in the new input stream. * @param thunk the code to execute with * the new input stream active - * @return the results of `thunk` - * @see `withIn[T](reader:Reader)(thunk: =>T)` + * @return the results of `thunk` + * @see `withIn[T](reader:Reader)(thunk: =>T)` + * @group io-redefinition */ def withIn[T](in: InputStream)(thunk: =>T): T = withIn(new InputStreamReader(in))(thunk) @@ -126,6 +241,7 @@ object Console extends DeprecatedConsole with AnsiColor { /** Prints an object to `out` using its `toString` method. * * @param obj the object to print; may be null. + * @group console-output */ def print(obj: Any) { out.print(if (null == obj) "null" else obj.toString()) @@ -134,29 +250,31 @@ object Console extends DeprecatedConsole with AnsiColor { /** Flushes the output stream. This function is required when partial * output (i.e. output not terminated by a newline character) has * to be made visible on the terminal. + * @group console-output */ def flush() { out.flush() } /** Prints a newline character on the default output. + * @group console-output */ def println() { out.println() } /** Prints out an object to the default output, followed by a newline character. * * @param x the object to print. + * @group console-output */ def println(x: Any) { out.println(x) } /** Prints its arguments as a formatted string to the default output, * based on a string pattern (in a fashion similar to printf in C). * - * The interpretation of the formatting patterns is described in - * - * `java.util.Formatter`. + * The interpretation of the formatting patterns is described in [[java.util.Formatter]]. * * @param text the pattern for formatting the arguments. * @param args the arguments used to instantiating the pattern. * @throws java.lang.IllegalArgumentException if there was a problem with the format string or arguments + * @group console-output */ def printf(text: String, args: Any*) { out.print(text format (args : _*)) } } diff --git a/src/library/scala/io/AnsiColor.scala b/src/library/scala/io/AnsiColor.scala index 39e2e3b0caff..720049ba8e10 100644 --- a/src/library/scala/io/AnsiColor.scala +++ b/src/library/scala/io/AnsiColor.scala @@ -1,52 +1,163 @@ package scala package io +/** ANSI escape codes providing control over text formatting and color on supporting text terminals. + * + * ==ANSI Style and Control Codes== + * + * This group of escape codes provides control over text styling. For example, to turn on reverse video with bold and + * then turn off all styling embed these codes, + * + * {{{ + * import io.AnsiColor._ + * + * object ColorDemo extends App { + * + * println(s"$REVERSED${BOLD}Hello 1979!$RESET") + * } + * }}} + * + * ==Foreground and Background Colors== + * + * Embedding ANSI color codes in text output will control the text foreground and background colors. + * + * + * + * + * + * + * + * + * + * + * + *
ForegroundBackground
BLACK BLACK_B
RED RED_B
GREEN GREEN_B
YELLOW YELLOW_B
BLUE BLUE_B
MAGENTAMAGENTA_B
CYAN CYAN_B
WHITE WHITE_B
+ * + * @groupname style-control ANSI Style and Control Codes + * @groupprio style-control 101 + * + * @groupname color-black ANSI Black + * @groupdesc color-black
 
+ * @groupprio color-black 110 + * + * @groupname color-red ANSI Red + * @groupdesc color-red
 
+ * @groupprio color-red 120 + * + * @groupname color-green ANSI Green + * @groupdesc color-green
 
+ * @groupprio color-green 130 + * + * @groupname color-yellow ANSI Yellow + * @groupdesc color-yellow
 
+ * @groupprio color-yellow 140 + * + * @groupname color-blue ANSI Blue + * @groupdesc color-blue
 
+ * @groupprio color-blue 150 + * + * @groupname color-magenta ANSI Magenta + * @groupdesc color-magenta
 
+ * @groupprio color-magenta 160 + * + * @groupname color-cyan ANSI Cyan + * @groupdesc color-cyan
 
+ * @groupprio color-cyan 170 + * + * @groupname color-white ANSI White + * @groupdesc color-white
 
+ * @groupprio color-white 180 + */ trait AnsiColor { - /** Foreground color for ANSI black */ + /** Foreground color for ANSI black + * @group color-black + */ final val BLACK = "\u001b[30m" - /** Foreground color for ANSI red */ + /** Foreground color for ANSI red + * @group color-red + */ final val RED = "\u001b[31m" - /** Foreground color for ANSI green */ + /** Foreground color for ANSI green + * @group color-green + */ final val GREEN = "\u001b[32m" - /** Foreground color for ANSI yellow */ + /** Foreground color for ANSI yellow + * @group color-yellow + */ final val YELLOW = "\u001b[33m" - /** Foreground color for ANSI blue */ + /** Foreground color for ANSI blue + * @group color-blue + */ final val BLUE = "\u001b[34m" - /** Foreground color for ANSI magenta */ + /** Foreground color for ANSI magenta + * @group color-magenta + */ final val MAGENTA = "\u001b[35m" - /** Foreground color for ANSI cyan */ + /** Foreground color for ANSI cyan + * @group color-cyan + */ final val CYAN = "\u001b[36m" - /** Foreground color for ANSI white */ + /** Foreground color for ANSI white + * @group color-white + */ final val WHITE = "\u001b[37m" - /** Background color for ANSI black */ + /** Background color for ANSI black + * @group color-black + */ final val BLACK_B = "\u001b[40m" - /** Background color for ANSI red */ + /** Background color for ANSI red + * @group color-red + */ final val RED_B = "\u001b[41m" - /** Background color for ANSI green */ + /** Background color for ANSI green + * @group color-green + */ final val GREEN_B = "\u001b[42m" - /** Background color for ANSI yellow */ + /** Background color for ANSI yellow + * @group color-yellow + */ final val YELLOW_B = "\u001b[43m" - /** Background color for ANSI blue */ + /** Background color for ANSI blue + * @group color-blue + */ final val BLUE_B = "\u001b[44m" - /** Background color for ANSI magenta */ + /** Background color for ANSI magenta + * @group color-magenta + */ final val MAGENTA_B = "\u001b[45m" - /** Background color for ANSI cyan */ + /** Background color for ANSI cyan + * @group color-cyan + */ final val CYAN_B = "\u001b[46m" - /** Background color for ANSI white */ + /** Background color for ANSI white + * @group color-white + */ final val WHITE_B = "\u001b[47m" - /** Reset ANSI styles */ + /** Reset ANSI styles + * @group style-control + */ final val RESET = "\u001b[0m" - /** ANSI bold */ + /** ANSI bold + * @group style-control + */ final val BOLD = "\u001b[1m" - /** ANSI underlines */ + /** ANSI underlines + * @group style-control + */ final val UNDERLINED = "\u001b[4m" - /** ANSI blink */ + /** ANSI blink + * @group style-control + */ final val BLINK = "\u001b[5m" - /** ANSI reversed */ + /** ANSI reversed + * @group style-control + */ final val REVERSED = "\u001b[7m" - /** ANSI invisible */ + /** ANSI invisible + * @group style-control + */ final val INVISIBLE = "\u001b[8m" } From 5450ae6102eaeb8ec0f9b524bf43ac5f604b5074 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 23 May 2016 10:12:41 -0700 Subject: [PATCH 054/153] SI-7898 Report paste errors improvedly Use a "label" for errors, so that script names are shown. Position is still wrong for scripts in REPL. Initial scripts are run with `ILoop.echo` and results printing turned off, but reporter still enabled. --- .../scala/tools/nsc/interpreter/ILoop.scala | 20 ++++++++------- .../scala/tools/nsc/interpreter/IMain.scala | 25 ++++++++++++------- test/files/run/t9170.scala | 2 +- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 4e0f60cf2b68..7dab371cafd6 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -1,5 +1,5 @@ /* NSC -- new Scala compiler - * Copyright 2005-2015 LAMP/EPFL + * Copyright 2005-2016 LAMP/EPFL * @author Alexander Spoon */ package scala @@ -15,7 +15,7 @@ import scala.tools.asm.ClassReader import scala.util.Properties.{ jdkHome, javaVersion, versionString, javaVmName } import scala.tools.nsc.util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream } import scala.reflect.classTag -import scala.reflect.internal.util.{ BatchSourceFile, ScalaClassLoader } +import scala.reflect.internal.util.{ BatchSourceFile, ScalaClassLoader, NoPosition } import ScalaClassLoader._ import scala.reflect.io.{ File, Directory } import scala.tools.util._ @@ -181,9 +181,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) out.flush() } // turn off intp reporter and our echo - def mumly[A](op: =>A): A = + def mumly[A](op: => A): A = if (isReplDebug) op - else intp beSilentDuring { + else intp beQuietDuring { val saved = mum mum = true try op finally mum = saved @@ -576,9 +576,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } - def withFile[A](filename: String)(action: File => A): Option[A] = { + def withFile[A](filename: String)(action: File => A): Option[A] = intp.withLabel(filename) { val res = Some(File(filename)) filter (_.exists) map action - if (res.isEmpty) echo("That file does not exist") // courtesy side-effect + if (res.isEmpty) intp.reporter.warning(NoPosition, s"File `$filename' does not exist.") // courtesy side-effect res } @@ -715,6 +715,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) */ def pasteCommand(arg: String): Result = { var shouldReplay: Option[String] = None + var label = "" def result = Result(keepRunning = true, shouldReplay) val (raw, file, margin) = if (arg.isEmpty) (false, None, None) @@ -735,6 +736,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } val code = (file, margin) match { case (Some(name), None) => + label = name withFile(name) { f => shouldReplay = Some(s":paste $arg") val s = f.slurp.trim @@ -757,17 +759,17 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) text } def interpretCode() = { - val res = intp interpret code + val res = intp.withLabel(label)(intp interpret code) // if input is incomplete, let the compiler try to say why if (res == IR.Incomplete) { echo("The pasted code is incomplete!\n") // Remembrance of Things Pasted in an object - val errless = intp compileSources new BatchSourceFile("", s"object pastel {\n$code\n}") + val errless = intp compileSources new BatchSourceFile(label, s"object pastel {\n$code\n}") if (errless) echo("...but compilation found no error? Good luck with that.") } } def compileCode() = { - val errless = intp compileSources new BatchSourceFile("", code) + val errless = intp compileSources new BatchSourceFile(label, code) if (!errless) echo("There were compilation errors!") } if (code.nonEmpty) { diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index ef6ab4063a39..1e7a9cefed04 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -1,5 +1,5 @@ /* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL + * Copyright 2005-2016 LAMP/EPFL * @author Martin Odersky */ @@ -74,13 +74,14 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set lazy val isClassBased: Boolean = settings.Yreplclassbased.value - private[nsc] var printResults = true // whether to print result lines - private[nsc] var totalSilence = false // whether to print anything - private var _initializeComplete = false // compiler is initialized - private var _isInitialized: Future[Boolean] = null // set up initialization future - private var bindExceptions = true // whether to bind the lastException variable - private var _executionWrapper = "" // code to be wrapped around all lines - var partialInput: String = "" // code accumulated in multi-line REPL input + private[nsc] var printResults = true // whether to print result lines + private[nsc] var totalSilence = false // whether to print anything + private var _initializeComplete = false // compiler is initialized + private var _isInitialized: Future[Boolean] = null // set up initialization future + private var bindExceptions = true // whether to bind the lastException variable + private var _executionWrapper = "" // code to be wrapped around all lines + var partialInput: String = "" // code accumulated in multi-line REPL input + private var label = "" // compilation unit name for reporting /** We're going to go to some trouble to initialize the compiler asynchronously. * It's critical that nothing call into it until it's been initialized or we will @@ -108,6 +109,12 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set try body finally if (!saved) settings.nowarn.value = false } + // Apply a temporary label for compilation (for example, script name) + def withLabel[A](temp: String)(body: => A): A = { + val saved = label + label = temp + try body finally label = saved + } /** construct an interpreter that reports to Console */ def this(settings: Settings, out: JPrintWriter) = this(null, settings, out) @@ -810,7 +817,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set case Right(result) => Right(result) } - def compile(source: String): Boolean = compileAndSaveRun("", source) + def compile(source: String): Boolean = compileAndSaveRun(label, source) /** The innermost object inside the wrapper, found by * following accessPath into the outer one. diff --git a/test/files/run/t9170.scala b/test/files/run/t9170.scala index f39467bc250b..87471fb1294d 100644 --- a/test/files/run/t9170.scala +++ b/test/files/run/t9170.scala @@ -44,7 +44,7 @@ object Y { // Exiting paste mode, now interpreting. -:13: error: double definition: +:13: error: double definition: def f[A](a: => A): Int at line 12 and def f[A](a: => Either[Exception,A]): Int at line 13 have same type after erasure: (a: Function0)Int From 892a6d6878accb67e3fe68aefaa256396db05a90 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Fri, 20 May 2016 12:49:25 +0100 Subject: [PATCH 055/153] SI-2712 Add support for higher order unification --- bincompat-forward.whitelist.conf | 4 + project/ScalaOptionParser.scala | 2 +- .../tools/nsc/settings/ScalaSettings.scala | 1 + .../scala/reflect/internal/Types.scala | 40 +++++- .../internal/settings/MutableSettings.scala | 1 + .../scala/reflect/runtime/Settings.scala | 1 + test/files/neg/t2712-1.check | 13 ++ test/files/neg/t2712-1.scala | 8 ++ test/files/neg/t2712-2.check | 13 ++ test/files/neg/t2712-2.flags | 1 + test/files/neg/t2712-2.scala | 18 +++ test/files/neg/t2712-3.check | 6 + test/files/neg/t2712-3.scala | 18 +++ test/files/neg/t2712.flags | 1 + test/files/pos/t2712-1.flags | 1 + test/files/pos/t2712-1.scala | 9 ++ test/files/pos/t2712-2.flags | 2 + test/files/pos/t2712-2.scala | 25 ++++ test/files/pos/t2712-3.flags | 2 + test/files/pos/t2712-3.scala | 24 ++++ test/files/pos/t2712-4.flags | 2 + test/files/pos/t2712-4.scala | 17 +++ test/files/pos/t2712-5.flags | 1 + test/files/pos/t2712-5.scala | 29 ++++ test/files/pos/t2712-6.flags | 1 + test/files/pos/t2712-6.scala | 12 ++ test/files/pos/t2712-7.flags | 1 + test/files/pos/t2712-7.scala | 15 +++ test/files/pos/t5683.flags | 1 + test/files/pos/t5683.scala | 23 ++++ test/files/pos/t6895b.flags | 2 + test/files/pos/t6895b.scala | 39 ++++++ .../run/inferred-type-constructors-hou.check | 56 ++++++++ .../run/inferred-type-constructors-hou.flags | 1 + .../run/inferred-type-constructors-hou.scala | 125 ++++++++++++++++++ 35 files changed, 509 insertions(+), 6 deletions(-) create mode 100644 test/files/neg/t2712-1.check create mode 100644 test/files/neg/t2712-1.scala create mode 100644 test/files/neg/t2712-2.check create mode 100644 test/files/neg/t2712-2.flags create mode 100644 test/files/neg/t2712-2.scala create mode 100644 test/files/neg/t2712-3.check create mode 100644 test/files/neg/t2712-3.scala create mode 100644 test/files/neg/t2712.flags create mode 100644 test/files/pos/t2712-1.flags create mode 100644 test/files/pos/t2712-1.scala create mode 100644 test/files/pos/t2712-2.flags create mode 100644 test/files/pos/t2712-2.scala create mode 100644 test/files/pos/t2712-3.flags create mode 100644 test/files/pos/t2712-3.scala create mode 100644 test/files/pos/t2712-4.flags create mode 100644 test/files/pos/t2712-4.scala create mode 100644 test/files/pos/t2712-5.flags create mode 100644 test/files/pos/t2712-5.scala create mode 100644 test/files/pos/t2712-6.flags create mode 100644 test/files/pos/t2712-6.scala create mode 100644 test/files/pos/t2712-7.flags create mode 100644 test/files/pos/t2712-7.scala create mode 100644 test/files/pos/t5683.flags create mode 100644 test/files/pos/t5683.scala create mode 100644 test/files/pos/t6895b.flags create mode 100644 test/files/pos/t6895b.scala create mode 100644 test/files/run/inferred-type-constructors-hou.check create mode 100644 test/files/run/inferred-type-constructors-hou.flags create mode 100644 test/files/run/inferred-type-constructors-hou.scala diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 2d32e3e9da8c..be4a44c4da21 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -478,6 +478,10 @@ filter { { matchName="scala.concurrent.impl.Promise$DefaultPromise" problemName=MissingTypesProblem + }, + { + matchName="scala.reflect.runtime.Settings.YpartialUnification" + problemName=MissingMethodProblem } ] } diff --git a/project/ScalaOptionParser.scala b/project/ScalaOptionParser.scala index f2fd4d86d7c0..6658b6efc62d 100644 --- a/project/ScalaOptionParser.scala +++ b/project/ScalaOptionParser.scala @@ -86,7 +86,7 @@ object ScalaOptionParser { "-Yeta-expand-keeps-star", "-Yide-debug", "-Yinfer-argument-types", "-Yinfer-by-name", "-Yissue-debug", "-Ylog-classpath", "-Ymacro-debug-lite", "-Ymacro-debug-verbose", "-Ymacro-no-expand", "-Yno-completion", "-Yno-generic-signatures", "-Yno-imports", "-Yno-predef", - "-Yoverride-objects", "-Yoverride-vars", "-Ypatmat-debug", "-Yno-adapted-args", "-Ypos-debug", "-Ypresentation-debug", + "-Yoverride-objects", "-Yoverride-vars", "-Ypatmat-debug", "-Yno-adapted-args", "-Ypartial-unification", "-Ypos-debug", "-Ypresentation-debug", "-Ypresentation-strict", "-Ypresentation-verbose", "-Yquasiquote-debug", "-Yrangepos", "-Yreify-copypaste", "-Yreify-debug", "-Yrepl-class-based", "-Yrepl-sync", "-Yshow-member-pos", "-Yshow-symkinds", "-Yshow-symowners", "-Yshow-syms", "-Yshow-trees", "-Yshow-trees-compact", "-Yshow-trees-stringified", "-Ytyper-debug", "-Ywarn-adapted-args", "-Ywarn-dead-code", "-Ywarn-inaccessible", "-Ywarn-infer-any", "-Ywarn-nullary-override", "-Ywarn-nullary-unit", "-Ywarn-numeric-widen", "-Ywarn-unused", "-Ywarn-unused-import", "-Ywarn-value-discard", diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 9a0d86a94df1..dcbff2426507 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -201,6 +201,7 @@ trait ScalaSettings extends AbsScalaSettings val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").withDeprecationMessage(removalIn212) val inferByName = BooleanSetting ("-Yinfer-by-name", "Allow inference of by-name types. This is a temporary option to ease transition. See SI-7899.").withDeprecationMessage(removalIn212) val YdisableFlatCpCaching = BooleanSetting ("-YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.") + val YpartialUnification = BooleanSetting ("-Ypartial-unification", "Enable partial unification in type constructor inference") val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly() val Ydelambdafy = ChoiceSetting ("-Ydelambdafy", "strategy", "Strategy used for translating lambdas into JVM code.", List("inline", "method"), "method") diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index de82a6a0b26c..a649f6f92658 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3131,13 +3131,43 @@ trait Types */ def unifyFull(tpe: Type): Boolean = { def unifySpecific(tp: Type) = { - sameLength(typeArgs, tp.typeArgs) && { - val lhs = if (isLowerBound) tp.typeArgs else typeArgs - val rhs = if (isLowerBound) typeArgs else tp.typeArgs + val tpTypeArgs = tp.typeArgs + val arityDelta = compareLengths(typeArgs, tpTypeArgs) + if (arityDelta == 0) { + val lhs = if (isLowerBound) tpTypeArgs else typeArgs + val rhs = if (isLowerBound) typeArgs else tpTypeArgs // This is a higher-kinded type var with same arity as tp. // If so (see SI-7517), side effect: adds the type constructor itself as a bound. - isSubArgs(lhs, rhs, params, AnyDepth) && { addBound(tp.typeConstructor); true } - } + isSubArgs(lhs, rhs, params, AnyDepth) && {addBound(tp.typeConstructor); true} + } else if (settings.YpartialUnification && arityDelta < 0 && typeArgs.nonEmpty) { + // Simple algorithm as suggested by Paul Chiusano in the comments on SI-2712 + // + // https://issues.scala-lang.org/browse/SI-2712?focusedCommentId=61270 + // + // Treat the type constructor as curried and partially applied, we treat a prefix + // as constants and solve for the suffix. For the example in the ticket, unifying + // M[A] with Int => Int this unifies as, + // + // M[t] = [t][Int => t] --> abstract on the right to match the expected arity + // A = Int --> capture the remainder on the left + // + // A more "natural" unifier might be M[t] = [t][t => t]. There's lots of scope for + // experimenting with alternatives here. + val numCaptured = tpTypeArgs.length - typeArgs.length + val (captured, abstractedArgs) = tpTypeArgs.splitAt(numCaptured) + + val (lhs, rhs) = + if (isLowerBound) (abstractedArgs, typeArgs) + else (typeArgs, abstractedArgs) + + isSubArgs(lhs, rhs, params, AnyDepth) && { + val tpSym = tp.typeSymbolDirect + val abstractedTypeParams = tpSym.typeParams.drop(numCaptured).map(_.cloneSymbol(tpSym)) + + addBound(PolyType(abstractedTypeParams, appliedType(tp.typeConstructor, captured ++ abstractedTypeParams.map(_.tpeHK)))) + true + } + } else false } // The type with which we can successfully unify can be hidden // behind singleton types and type aliases. diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala index e75b3dff3d5d..5a2c8024768a 100644 --- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala @@ -53,6 +53,7 @@ abstract class MutableSettings extends AbsSettings { def printtypes: BooleanSetting def uniqid: BooleanSetting def verbose: BooleanSetting + def YpartialUnification: BooleanSetting def Yrecursion: IntSetting def maxClassfileName: IntSetting diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala index b1d7fde1b446..3b33f089e1ae 100644 --- a/src/reflect/scala/reflect/runtime/Settings.scala +++ b/src/reflect/scala/reflect/runtime/Settings.scala @@ -47,6 +47,7 @@ private[reflect] class Settings extends MutableSettings { val printtypes = new BooleanSetting(false) val uniqid = new BooleanSetting(false) val verbose = new BooleanSetting(false) + val YpartialUnification = new BooleanSetting(false) val Yrecursion = new IntSetting(0) val maxClassfileName = new IntSetting(255) diff --git a/test/files/neg/t2712-1.check b/test/files/neg/t2712-1.check new file mode 100644 index 000000000000..61e4b6b1499c --- /dev/null +++ b/test/files/neg/t2712-1.check @@ -0,0 +1,13 @@ +t2712-1.scala:7: error: no type parameters for method foo: (m: M[A])Unit exist so that it can be applied to arguments (test.Two[Int,String]) + --- because --- +argument expression's type is not compatible with formal parameter type; + found : test.Two[Int,String] + required: ?M[?A] + def test(ma: Two[Int, String]) = foo(ma) // should fail with -Ypartial-unification *disabled* + ^ +t2712-1.scala:7: error: type mismatch; + found : test.Two[Int,String] + required: M[A] + def test(ma: Two[Int, String]) = foo(ma) // should fail with -Ypartial-unification *disabled* + ^ +two errors found diff --git a/test/files/neg/t2712-1.scala b/test/files/neg/t2712-1.scala new file mode 100644 index 000000000000..f7967d71b689 --- /dev/null +++ b/test/files/neg/t2712-1.scala @@ -0,0 +1,8 @@ +package test + +trait Two[A, B] + +object Test { + def foo[M[_], A](m: M[A]) = () + def test(ma: Two[Int, String]) = foo(ma) // should fail with -Ypartial-unification *disabled* +} diff --git a/test/files/neg/t2712-2.check b/test/files/neg/t2712-2.check new file mode 100644 index 000000000000..ea19e33e2c55 --- /dev/null +++ b/test/files/neg/t2712-2.check @@ -0,0 +1,13 @@ +t2712-2.scala:16: error: type mismatch; + found : test.Foo + required: test.Two[test.X1,Object] +Note: test.X2 <: Object (and test.Foo <: test.Two[test.X1,test.X2]), but trait Two is invariant in type B. +You may wish to define B as +B instead. (SLS 4.5) + test1(foo): One[X3] // fails with -Ypartial-unification enabled + ^ +t2712-2.scala:16: error: type mismatch; + found : test.Two[test.X1,Object] + required: test.One[test.X3] + test1(foo): One[X3] // fails with -Ypartial-unification enabled + ^ +two errors found diff --git a/test/files/neg/t2712-2.flags b/test/files/neg/t2712-2.flags new file mode 100644 index 000000000000..41565c7e32bd --- /dev/null +++ b/test/files/neg/t2712-2.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/neg/t2712-2.scala b/test/files/neg/t2712-2.scala new file mode 100644 index 000000000000..85ed52348903 --- /dev/null +++ b/test/files/neg/t2712-2.scala @@ -0,0 +1,18 @@ +package test + +class X1 +class X2 +class X3 + +trait One[A] +trait Two[A, B] + +class Foo extends Two[X1, X2] with One[X3] +object Test { + def test1[M[_], A](x: M[A]): M[A] = x + + val foo = new Foo + + test1(foo): One[X3] // fails with -Ypartial-unification enabled + test1(foo): Two[X1, X2] // fails without -Ypartial-unification +} diff --git a/test/files/neg/t2712-3.check b/test/files/neg/t2712-3.check new file mode 100644 index 000000000000..a84d96bf09c9 --- /dev/null +++ b/test/files/neg/t2712-3.check @@ -0,0 +1,6 @@ +t2712-3.scala:17: error: type mismatch; + found : test.One[test.X3] + required: test.Two[test.X1,test.X2] + test1(foo): Two[X1, X2] // fails without -Ypartial-unification + ^ +one error found diff --git a/test/files/neg/t2712-3.scala b/test/files/neg/t2712-3.scala new file mode 100644 index 000000000000..85ed52348903 --- /dev/null +++ b/test/files/neg/t2712-3.scala @@ -0,0 +1,18 @@ +package test + +class X1 +class X2 +class X3 + +trait One[A] +trait Two[A, B] + +class Foo extends Two[X1, X2] with One[X3] +object Test { + def test1[M[_], A](x: M[A]): M[A] = x + + val foo = new Foo + + test1(foo): One[X3] // fails with -Ypartial-unification enabled + test1(foo): Two[X1, X2] // fails without -Ypartial-unification +} diff --git a/test/files/neg/t2712.flags b/test/files/neg/t2712.flags new file mode 100644 index 000000000000..41565c7e32bd --- /dev/null +++ b/test/files/neg/t2712.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-1.flags b/test/files/pos/t2712-1.flags new file mode 100644 index 000000000000..41565c7e32bd --- /dev/null +++ b/test/files/pos/t2712-1.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-1.scala b/test/files/pos/t2712-1.scala new file mode 100644 index 000000000000..4f84c9df5edd --- /dev/null +++ b/test/files/pos/t2712-1.scala @@ -0,0 +1,9 @@ +package test + +// Original test case from, +// +// https://issues.scala-lang.org/browse/SI-2712 +object Test { + def meh[M[_], A](x: M[A]): M[A] = x + meh{(x: Int) => x} // solves ?M = [X] Int => X and ?A = Int ... +} diff --git a/test/files/pos/t2712-2.flags b/test/files/pos/t2712-2.flags new file mode 100644 index 000000000000..7d49efbb8e6c --- /dev/null +++ b/test/files/pos/t2712-2.flags @@ -0,0 +1,2 @@ +-Ypartial-unification + diff --git a/test/files/pos/t2712-2.scala b/test/files/pos/t2712-2.scala new file mode 100644 index 000000000000..39f22dd92a79 --- /dev/null +++ b/test/files/pos/t2712-2.scala @@ -0,0 +1,25 @@ +package test + +// See: https://github.com/milessabin/si2712fix-demo/issues/3 +object Test { + trait A[T1, T2] { } + trait B[T1, T2] { } + class C[T] extends A[T, Long] with B[T, Double] + class CB extends A[Boolean, Long] with B[Boolean, Double] + + trait A2[T] + trait B2[T] + class C2[T] extends A2[T] with B2[T] + class CB2 extends A2[Boolean] with B2[Boolean] + + def meh[M[_], A](x: M[A]): M[A] = x + + val m0 = meh(new C[Boolean]) + m0: C[Boolean] + val m1 = meh(new CB) + m1: A[Boolean, Long] + val m2 = meh(new C2[Boolean]) + m2: C2[Boolean] + val m3 = meh(new CB2) + m3: A2[Boolean] +} diff --git a/test/files/pos/t2712-3.flags b/test/files/pos/t2712-3.flags new file mode 100644 index 000000000000..7d49efbb8e6c --- /dev/null +++ b/test/files/pos/t2712-3.flags @@ -0,0 +1,2 @@ +-Ypartial-unification + diff --git a/test/files/pos/t2712-3.scala b/test/files/pos/t2712-3.scala new file mode 100644 index 000000000000..46445f9289f7 --- /dev/null +++ b/test/files/pos/t2712-3.scala @@ -0,0 +1,24 @@ +package test + +object Test1 { + class Foo[T, F[_]] + def meh[M[_[_]], F[_]](x: M[F]): M[F] = x + meh(new Foo[Int, List]) // solves ?M = [X[_]]Foo[Int, X[_]] ?A = List ... +} + +object Test2 { + trait TC[T] + class Foo[F[_], G[_]] + def meh[G[_[_]]](g: G[TC]) = ??? + meh(new Foo[TC, TC]) // solves ?G = [X[_]]Foo[TC, X] +} + +object Test3 { + trait TC[F[_]] + trait TC2[F[_]] + class Foo[F[_[_]], G[_[_]]] + new Foo[TC, TC2] + + def meh[G[_[_[_]]]](g: G[TC2]) = ??? + meh(new Foo[TC, TC2]) // solves ?G = [X[_[_]]]Foo[TC, X] +} diff --git a/test/files/pos/t2712-4.flags b/test/files/pos/t2712-4.flags new file mode 100644 index 000000000000..7d49efbb8e6c --- /dev/null +++ b/test/files/pos/t2712-4.flags @@ -0,0 +1,2 @@ +-Ypartial-unification + diff --git a/test/files/pos/t2712-4.scala b/test/files/pos/t2712-4.scala new file mode 100644 index 000000000000..3e2e5cddaedf --- /dev/null +++ b/test/files/pos/t2712-4.scala @@ -0,0 +1,17 @@ +package test + +object Test1 { + trait X + trait Y extends X + class Foo[T, U <: X] + def meh[M[_ <: A], A](x: M[A]): M[A] = x + meh(new Foo[Int, Y]) +} + +object Test2 { + trait X + trait Y extends X + class Foo[T, U >: Y] + def meh[M[_ >: A], A](x: M[A]): M[A] = x + meh(new Foo[Int, X]) +} diff --git a/test/files/pos/t2712-5.flags b/test/files/pos/t2712-5.flags new file mode 100644 index 000000000000..41565c7e32bd --- /dev/null +++ b/test/files/pos/t2712-5.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-5.scala b/test/files/pos/t2712-5.scala new file mode 100644 index 000000000000..ed96d4c06fcc --- /dev/null +++ b/test/files/pos/t2712-5.scala @@ -0,0 +1,29 @@ +package test + +import scala.language.higherKinds + +trait Functor[F[_]] { + def map[A, B](f: A => B, fa: F[A]): F[B] +} + +object Functor { + implicit def function[A]: Functor[({ type l[B] = A => B })#l] = + new Functor[({ type l[B] = A => B })#l] { + def map[C, B](cb: C => B, ac: A => C): A => B = cb compose ac + } +} + +object FunctorSyntax { + implicit class FunctorOps[F[_], A](fa: F[A])(implicit F: Functor[F]) { + def map[B](f: A => B): F[B] = F.map(f, fa) + } +} + +object Test { + + val f: Int => String = _.toString + + import FunctorSyntax._ + + f.map((s: String) => s.reverse) +} diff --git a/test/files/pos/t2712-6.flags b/test/files/pos/t2712-6.flags new file mode 100644 index 000000000000..41565c7e32bd --- /dev/null +++ b/test/files/pos/t2712-6.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-6.scala b/test/files/pos/t2712-6.scala new file mode 100644 index 000000000000..eefe769ad652 --- /dev/null +++ b/test/files/pos/t2712-6.scala @@ -0,0 +1,12 @@ +package test + +object Tags { + type Tagged[A, T] = {type Tag = T; type Self = A} + + type @@[T, Tag] = Tagged[T, Tag] + + trait Disjunction + + def meh[M[_], A](ma: M[A]): M[A] = ma + meh(null.asInstanceOf[Int @@ Disjunction]) +} diff --git a/test/files/pos/t2712-7.flags b/test/files/pos/t2712-7.flags new file mode 100644 index 000000000000..41565c7e32bd --- /dev/null +++ b/test/files/pos/t2712-7.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t2712-7.scala b/test/files/pos/t2712-7.scala new file mode 100644 index 000000000000..d9c5243f132d --- /dev/null +++ b/test/files/pos/t2712-7.scala @@ -0,0 +1,15 @@ +package test + +// Cats Xor, Scalaz \/, scala.util.Either +sealed abstract class Xor[+A, +B] extends Product with Serializable +object Xor { + final case class Left[+A](a: A) extends (A Xor Nothing) + final case class Right[+B](b: B) extends (Nothing Xor B) +} + +object TestXor { + import Xor._ + def meh[F[_], A, B](fa: F[A])(f: A => B): F[B] = ??? + meh(new Right(23): Xor[Boolean, Int])(_ < 13) + meh(new Left(true): Xor[Boolean, Int])(_ < 13) +} diff --git a/test/files/pos/t5683.flags b/test/files/pos/t5683.flags new file mode 100644 index 000000000000..41565c7e32bd --- /dev/null +++ b/test/files/pos/t5683.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/pos/t5683.scala b/test/files/pos/t5683.scala new file mode 100644 index 000000000000..05ab03579274 --- /dev/null +++ b/test/files/pos/t5683.scala @@ -0,0 +1,23 @@ +object Test { + trait NT[X] + trait W[W, A] extends NT[Int] + type StringW[T] = W[String, T] + trait K[M[_], A, B] + + def k[M[_], B](f: Int => M[B]): K[M, Int, B] = null + + val okay1: K[StringW,Int,Int] = k{ (y: Int) => null: StringW[Int] } + val okay2 = k[StringW,Int]{ (y: Int) => null: W[String, Int] } + + val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] } + + // remove `extends NT[Int]`, and the last line gives an inference error + // rather than a crash. + // test/files/pos/t5683.scala:12: error: no type parameters for method k: (f: Int => M[B])Test.K[M,Int,B] exist so that it can be applied to arguments (Int => Test.W[String,Int]) + // --- because --- + // argument expression's type is not compatible with formal parameter type; + // found : Int => Test.W[String,Int] + // required: Int => ?M[?B] + // val crash: K[StringW,Int,Int] = k{ (y: Int) => null: W[String, Int] } + // ^ +} diff --git a/test/files/pos/t6895b.flags b/test/files/pos/t6895b.flags new file mode 100644 index 000000000000..7d49efbb8e6c --- /dev/null +++ b/test/files/pos/t6895b.flags @@ -0,0 +1,2 @@ +-Ypartial-unification + diff --git a/test/files/pos/t6895b.scala b/test/files/pos/t6895b.scala new file mode 100644 index 000000000000..c46506501108 --- /dev/null +++ b/test/files/pos/t6895b.scala @@ -0,0 +1,39 @@ +trait Foo[F[_]] +trait Bar[F[_], A] + +trait Or[A, B] + +class Test { + implicit def orFoo[A]: Foo[({type L[X] = Or[A, X]})#L] = ??? + implicit def barFoo[F[_]](implicit f: Foo[F]): Foo[({type L[X] = Bar[F, X]})#L] = ??? + + // Now we can define a couple of type aliases: + type StringOr[X] = Or[String, X] + type BarStringOr[X] = Bar[StringOr, X] + + // ok + implicitly[Foo[BarStringOr]] + barFoo[StringOr](null) : Foo[BarStringOr] + barFoo(null) : Foo[BarStringOr] + + // nok + implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]] + // Let's write the application explicitly, and then + // compile with just this line enabled and -explaintypes. + barFoo(null) : Foo[({type L[X] = Bar[StringOr, X]})#L] + + // Foo[[X]Bar[F,X]] <: Foo[[X]Bar[[X]Or[String,X],X]]? + // Bar[[X]Or[String,X],X] <: Bar[F,X]? + // F[_] <: Or[String,_]? + // false + // false + // false + + // Note that the type annotation above is typechecked as + // Foo[[X]Bar[[X]Or[String,X],X]], ie the type alias `L` + // is eta expanded. + // + // This is done so that it does not escape its defining scope. + // However, one this is done, higher kinded inference + // no longer is able to unify F with `StringOr` (SI-2712) +} diff --git a/test/files/run/inferred-type-constructors-hou.check b/test/files/run/inferred-type-constructors-hou.check new file mode 100644 index 000000000000..6b0982334189 --- /dev/null +++ b/test/files/run/inferred-type-constructors-hou.check @@ -0,0 +1,56 @@ +warning: there were two feature warnings; re-run with -feature for details + p.Iterable[Int] + p.Set[Int] + p.Seq[Int] + p.m.Set[Int] + p.m.Seq[Int] + private[m] p.m.ASet[Int] + p.i.Seq[Int] + private[i] p.i.ASet[Int] + private[i] p.i.ASeq[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Set[Int] + p.Iterable[Int] + p.Set[Int] + p.Iterable[Int] + p.Set[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + p.m.Set[Int] + p.Iterable[Int] + p.Set[Int] + p.Iterable[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + p.Seq[Int] + p.Iterable[Int] + private[p] p.ASet[Int] + private[p] p.AIterable[Int] + p.Iterable[Int] + p.i.Seq[Int] + private[p] p.AIterable[Int] + List[Nothing] + scala.collection.immutable.Vector[Nothing] + scala.collection.immutable.Map[Int,Int] + scala.collection.immutable.Set[Int] + Seq[Int] + Array[Int] + scala.collection.AbstractSet[Int] + Comparable[java.lang.String] + scala.collection.immutable.LinearSeq[Int] + Iterable[Int] diff --git a/test/files/run/inferred-type-constructors-hou.flags b/test/files/run/inferred-type-constructors-hou.flags new file mode 100644 index 000000000000..41565c7e32bd --- /dev/null +++ b/test/files/run/inferred-type-constructors-hou.flags @@ -0,0 +1 @@ +-Ypartial-unification diff --git a/test/files/run/inferred-type-constructors-hou.scala b/test/files/run/inferred-type-constructors-hou.scala new file mode 100644 index 000000000000..79a8653f686b --- /dev/null +++ b/test/files/run/inferred-type-constructors-hou.scala @@ -0,0 +1,125 @@ +package p { + trait TCon[+CC[X]] { + def fPublic: CC[Int] = ??? + private[p] def fPackagePrivate: CC[Int] = ??? + protected[p] def fPackageProtected: CC[Int] = ??? + } + trait Iterable[+A] extends TCon[Iterable] + trait Set[A] extends Iterable[A] with TCon[Set] + trait Seq[+A] extends Iterable[A] with TCon[Seq] + + private[p] abstract class AIterable[+A] extends Iterable[A] + private[p] abstract class ASeq[+A] extends AIterable[A] with Seq[A] + private[p] abstract class ASet[A] extends AIterable[A] with Set[A] + + package m { + private[m] abstract class ASeq[A] extends p.ASeq[A] with Seq[A] + private[m] abstract class ASet[A] extends p.ASet[A] with Set[A] + trait Set[A] extends p.Set[A] with TCon[Set] + trait Seq[A] extends p.Seq[A] with TCon[Seq] + trait BitSet extends ASet[Int] + trait IntSeq extends ASeq[Int] + } + + package i { + private[i] abstract class ASeq[+A] extends p.ASeq[A] with Seq[A] + private[i] abstract class ASet[A] extends p.ASet[A] with Set[A] + trait Set[A] extends p.Set[A] with TCon[Set] + trait Seq[+A] extends p.Seq[A] with TCon[Seq] + trait BitSet extends ASet[Int] + trait IntSeq extends ASeq[Int] + } +} + +object Test { + import scala.reflect.runtime.universe._ + // Complicated by the absence of usable type constructor type tags. + def extract[A, CC[X]](xs: CC[A]): CC[A] = xs + def whatis[T: TypeTag](x: T): Unit = { + val tpe = typeOf[T] + val access = tpe.typeSymbol.asInstanceOf[scala.reflect.internal.HasFlags].accessString.replaceAllLiterally("package ", "") + println(f"$access%15s $tpe") + } + + trait IntIterable extends p.Iterable[Int] + trait IntSet extends p.Set[Int] + trait IntSeq extends p.Seq[Int] + + trait MutableIntSet extends p.m.Set[Int] + trait MutableIntSeq extends p.m.Seq[Int] + + trait ImmutableIntSet extends p.i.Set[Int] + trait ImmutableIntSeq extends p.i.Seq[Int] + + def f1: IntIterable = null + def f2: IntSet = null + def f3: IntSeq = null + + def g1: MutableIntSet = null + def g2: MutableIntSeq = null + def g3: p.m.BitSet = null + + def h1: ImmutableIntSeq = null + def h2: p.i.BitSet = null + def h3: p.i.IntSeq = null + + def main(args: Array[String]): Unit = { + whatis(extract(f1)) + whatis(extract(f2)) + whatis(extract(f3)) + whatis(extract(g1)) + whatis(extract(g2)) + whatis(extract(g3)) + whatis(extract(h1)) + whatis(extract(h2)) + whatis(extract(h3)) + + whatis(extract(if (true) f1 else f2)) + whatis(extract(if (true) f1 else f3)) + whatis(extract(if (true) f1 else g1)) + whatis(extract(if (true) f1 else g2)) + whatis(extract(if (true) f1 else g3)) + whatis(extract(if (true) f1 else h1)) + whatis(extract(if (true) f1 else h2)) + whatis(extract(if (true) f1 else h3)) + whatis(extract(if (true) f2 else f3)) + whatis(extract(if (true) f2 else g1)) + whatis(extract(if (true) f2 else g2)) + whatis(extract(if (true) f2 else g3)) + whatis(extract(if (true) f2 else h1)) + whatis(extract(if (true) f2 else h2)) + whatis(extract(if (true) f2 else h3)) + whatis(extract(if (true) f3 else g1)) + whatis(extract(if (true) f3 else g2)) + whatis(extract(if (true) f3 else g3)) + whatis(extract(if (true) f3 else h1)) + whatis(extract(if (true) f3 else h2)) + whatis(extract(if (true) f3 else h3)) + whatis(extract(if (true) g1 else g2)) + whatis(extract(if (true) g1 else g3)) + whatis(extract(if (true) g1 else h1)) + whatis(extract(if (true) g1 else h2)) + whatis(extract(if (true) g1 else h3)) + whatis(extract(if (true) g2 else g3)) + whatis(extract(if (true) g2 else h1)) + whatis(extract(if (true) g2 else h2)) + whatis(extract(if (true) g2 else h3)) + whatis(extract(if (true) g3 else h1)) + whatis(extract(if (true) g3 else h2)) + whatis(extract(if (true) g3 else h3)) + whatis(extract(if (true) h1 else h2)) + whatis(extract(if (true) h1 else h3)) + whatis(extract(if (true) h2 else h3)) + + whatis(extract(Nil)) + whatis(extract(Vector())) + whatis(extract(Map[Int,Int]())) + whatis(extract(Set[Int]())) + whatis(extract(Seq[Int]())) + whatis(extract(Array[Int]())) + whatis(extract(scala.collection.immutable.BitSet(1))) + whatis(extract("abc")) + whatis(extract(if (true) Stream(1) else List(1))) + whatis(extract(if (true) Seq(1) else Set(1))) + } +} From bf478084fdf65c7bd156e2e6f04a96bfadf6986b Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Fri, 20 May 2016 12:49:42 +0100 Subject: [PATCH 056/153] -Xexperimental mode now only includes -Ypartial-unification --- src/compiler/scala/tools/nsc/settings/ScalaSettings.scala | 2 +- test/files/run/t5676.flags | 2 +- test/junit/scala/tools/nsc/settings/SettingsTest.scala | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index dcbff2426507..be34b1545380 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -30,7 +30,7 @@ trait ScalaSettings extends AbsScalaSettings protected def defaultClasspath = sys.env.getOrElse("CLASSPATH", ".") /** Enabled under -Xexperimental. */ - protected def experimentalSettings = List[BooleanSetting](YmethodInfer, overrideObjects, overrideVars) + protected def experimentalSettings = List[BooleanSetting](YpartialUnification) /** Enabled under -Xfuture. */ protected def futureSettings = List[BooleanSetting]() diff --git a/test/files/run/t5676.flags b/test/files/run/t5676.flags index e1b37447c953..73f1330c31df 100644 --- a/test/files/run/t5676.flags +++ b/test/files/run/t5676.flags @@ -1 +1 @@ --Xexperimental \ No newline at end of file +-Yoverride-objects diff --git a/test/junit/scala/tools/nsc/settings/SettingsTest.scala b/test/junit/scala/tools/nsc/settings/SettingsTest.scala index 01a235101144..0f2d206273b0 100644 --- a/test/junit/scala/tools/nsc/settings/SettingsTest.scala +++ b/test/junit/scala/tools/nsc/settings/SettingsTest.scala @@ -31,11 +31,11 @@ class SettingsTest { val s = new MutableSettings(msg => throw new IllegalArgumentException(msg)) val (ok, residual) = s.processArguments(args.toList, processAll = true) assert(residual.isEmpty) - s.YmethodInfer // among -Xexperimental + s.YpartialUnification // among -Xexperimental } assertTrue(check("-Xexperimental").value) - assertFalse(check("-Xexperimental", "-Yinfer-argument-types:false").value) - assertFalse(check("-Yinfer-argument-types:false", "-Xexperimental").value) + assertFalse(check("-Xexperimental", "-Ypartial-unification:false").value) + assertFalse(check("-Ypartial-unification:false", "-Xexperimental").value) } // for the given args, select the desired setting From b462e5a97b499bc91222014e45ec2439f56b46b7 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 24 May 2016 08:21:56 +0200 Subject: [PATCH 057/153] SI-7898 Label for parsing -i sources Text-based REPL pre-parses, so use the current label for errors. --- .../scala/tools/nsc/interpreter/IMain.scala | 2 +- test/files/run/repl-paste-parse.check | 6 +++++ test/files/run/repl-paste-parse.scala | 27 +++++++++++++++++++ test/files/run/repl-paste-parse.script | 1 + 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100755 test/files/run/repl-paste-parse.check create mode 100644 test/files/run/repl-paste-parse.scala create mode 100644 test/files/run/repl-paste-parse.script diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 1e7a9cefed04..dc8b6204c01e 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -1191,7 +1191,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set var isIncomplete = false def parse = { reporter.reset() - val trees = newUnitParser(line).parseStats() + val trees = newUnitParser(line, label).parseStats() if (reporter.hasErrors) Error(trees) else if (isIncomplete) Incomplete(trees) else Success(trees) diff --git a/test/files/run/repl-paste-parse.check b/test/files/run/repl-paste-parse.check new file mode 100755 index 000000000000..7b2148dc747f --- /dev/null +++ b/test/files/run/repl-paste-parse.check @@ -0,0 +1,6 @@ +Type in expressions for evaluation. Or try :help. + +scala> repl-paste-parse.script:1: error: illegal start of simple pattern +val case = 9 + ^ +:quit diff --git a/test/files/run/repl-paste-parse.scala b/test/files/run/repl-paste-parse.scala new file mode 100644 index 000000000000..e93ad4d02bb3 --- /dev/null +++ b/test/files/run/repl-paste-parse.scala @@ -0,0 +1,27 @@ + +import java.io.{ BufferedReader, StringReader, StringWriter, PrintWriter } + +import scala.tools.partest.DirectTest +import scala.tools.nsc.interpreter.ILoop +import scala.tools.nsc.GenericRunnerSettings + +object Test extends DirectTest { + override def extraSettings = s"-usejavacp -i $scriptPath" + def scriptPath = testPath.changeExtension("script") + override def newSettings(args: List[String]) = { + val ss = new GenericRunnerSettings(Console.println) + ss.processArguments(args, true) + ss + } + def code = "" + def show() = { + val r = new BufferedReader(new StringReader("")) + val w = new StringWriter + val p = new PrintWriter(w, true) + new ILoop(r, p).process(settings) + w.toString.lines foreach { s => + if (!s.startsWith("Welcome to Scala")) println(s) + } + } +} + diff --git a/test/files/run/repl-paste-parse.script b/test/files/run/repl-paste-parse.script new file mode 100644 index 000000000000..903f6e7b0c07 --- /dev/null +++ b/test/files/run/repl-paste-parse.script @@ -0,0 +1 @@ +val case = 9 From 60f28f9e6a330e91a0f1204917301d401a6fce72 Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Mon, 25 Apr 2016 16:33:04 -0700 Subject: [PATCH 058/153] SI-9522 release key reference when deleting from OpenHashMap This sets the key field in the hash table entry to its default value when an entry is deleted, so as not to unexpectedly retain an object reference, leading to a memory leak. Also includes incidental changes to the slot location algorithm that reduce the number of deleted entries. --- build.sbt | 3 +- build.xml | 1 + src/eclipse/repl/.classpath | 2 +- src/eclipse/test-junit/.classpath | 1 + .../collection/mutable/OpenHashMap.scala | 83 ++++++++++++------- .../collection/mutable/OpenHashMapTest.scala | 58 ++++++++++++- 6 files changed, 116 insertions(+), 32 deletions(-) diff --git a/build.sbt b/build.sbt index d592b86aff5d..2eb629f9235c 100644 --- a/build.sbt +++ b/build.sbt @@ -66,6 +66,7 @@ val scalaXmlDep = withoutScalaLang("org.scala-lang.modules" %% "scala-xml" % ver val partestDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest" % versionNumber("partest")) val junitDep = "junit" % "junit" % "4.11" val junitIntefaceDep = "com.novocode" % "junit-interface" % "0.11" % "test" +val jolDep = "org.openjdk.jol" % "jol-core" % "0.5" val asmDep = "org.scala-lang.modules" % "scala-asm" % versionProps("scala-asm.version") val jlineDep = "jline" % "jline" % versionProps("jline.version") val antDep = "org.apache.ant" % "ant" % "1.9.4" @@ -544,7 +545,7 @@ lazy val junit = project.in(file("test") / "junit") .settings(disablePublishing: _*) .settings( fork in Test := true, - libraryDependencies ++= Seq(junitDep, junitIntefaceDep), + libraryDependencies ++= Seq(junitDep, junitIntefaceDep, jolDep), testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"), unmanagedSourceDirectories in Test := List(baseDirectory.value) ) diff --git a/build.xml b/build.xml index 778bcc561b14..c1b0b228a1f9 100644 --- a/build.xml +++ b/build.xml @@ -277,6 +277,7 @@ TODO: + diff --git a/src/eclipse/repl/.classpath b/src/eclipse/repl/.classpath index 682377adc98b..141f84e6bb21 100644 --- a/src/eclipse/repl/.classpath +++ b/src/eclipse/repl/.classpath @@ -2,7 +2,7 @@ - + diff --git a/src/eclipse/test-junit/.classpath b/src/eclipse/test-junit/.classpath index 3635c8511272..1e1b51066312 100644 --- a/src/eclipse/test-junit/.classpath +++ b/src/eclipse/test-junit/.classpath @@ -11,6 +11,7 @@ + diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala index 5f8f5b9a0a32..5bea1634c4bf 100644 --- a/src/library/scala/collection/mutable/OpenHashMap.scala +++ b/src/library/scala/collection/mutable/OpenHashMap.scala @@ -21,10 +21,16 @@ object OpenHashMap { def apply[K, V](elems : (K, V)*) = new OpenHashMap[K, V] ++= elems def empty[K, V] = new OpenHashMap[K, V] - final private class OpenEntry[Key, Value](val key: Key, - val hash: Int, + /** A hash table entry. + * + * The entry is occupied if and only if its `value` is a `Some`; + * deleted if and only if its `value` is `None`. + * If its `key` is not the default value of type `Key`, the entry is occupied. + * If the entry is occupied, `hash` contains the hash value of `key`. + */ + final private class OpenEntry[Key, Value](var key: Key, + var hash: Int, var value: Option[Value]) - extends HashEntry[Key, OpenEntry[Key, Value]] private[mutable] def nextPositivePowerOfTwo(i : Int) = 1 << (32 - Integer.numberOfLeadingZeros(i - 1)) } @@ -64,7 +70,14 @@ extends AbstractMap[Key, Value] private[this] val actualInitialSize = OpenHashMap.nextPositivePowerOfTwo(initialSize) private var mask = actualInitialSize - 1 - private var table : Array[Entry] = new Array[Entry](actualInitialSize) + + /** The hash table. + * + * The table's entries are initialized to `null`, indication of an empty slot. + * A slot is either deleted or occupied if and only if the entry is non-`null`. + */ + private[this] var table = new Array[Entry](actualInitialSize) + private var _size = 0 private var deleted = 0 @@ -91,42 +104,43 @@ extends AbstractMap[Key, Value] table = new Array[Entry](newSize) mask = newSize - 1 oldTable.foreach( entry => - if (entry != null && entry.value != None) addEntry(entry)) + if (entry != null && entry.value != None) + table(findIndex(entry.key, entry.hash)) = entry ) deleted = 0 } /** Return the index of the first slot in the hash table (in probe order) - * that either is empty, or is or was last occupied by the given key. - */ - private[this] def findIndex(key: Key) : Int = findIndex(key, hashOf(key)) - - /** Return the index of the first slot in the hash table (in probe order) - * that either is empty, or is or was last occupied by the given key. - * - * This method is an optimization for when the hash value is in hand. + * that is, in order of preference, either occupied by the given key, deleted, or empty. * * @param hash hash value for `key` */ private[this] def findIndex(key: Key, hash: Int): Int = { var j = hash - var index = hash & mask var perturb = index - while(table(index) != null && - !(table(index).hash == hash && - table(index).key == key)){ + + /** Index of the first slot containing a deleted entry, or -1 if none found yet. */ + var firstDeletedIndex = -1 + + var entry = table(index) + while (entry != null) { + if (entry.hash == hash && entry.key == key && entry.value != None) + return index + + if (firstDeletedIndex == -1 && entry.value == None) + firstDeletedIndex = index + j = 5 * j + 1 + perturb perturb >>= 5 index = j & mask + entry = table(index) } - index - } - private[this] def addEntry(entry: Entry) = - if (entry != null) table(findIndex(entry.key, entry.hash)) = entry + if (firstDeletedIndex == -1) index else firstDeletedIndex + } override def update(key: Key, value: Value) { - put(key, hashOf(key), value) + put(key, value) } @deprecatedOverriding("+= should not be overridden in order to maintain consistency with put.", "2.11.0") @@ -150,6 +164,8 @@ extends AbstractMap[Key, Value] } else { val res = entry.value if (entry.value == None) { + entry.key = key + entry.hash = hash size += 1 deleted -= 1 modCount += 1 @@ -159,13 +175,22 @@ extends AbstractMap[Key, Value] } } + /** Delete the hash table slot contained in the given entry. */ + @inline + private[this] def deleteSlot(entry: Entry) = { + entry.key = null.asInstanceOf[Key] + entry.hash = 0 + entry.value = None + + size -= 1 + deleted += 1 + } + override def remove(key : Key): Option[Value] = { - val index = findIndex(key) - if (table(index) != null && table(index).value != None){ - val res = table(index).value - table(index).value = None - size -= 1 - deleted += 1 + val entry = table(findIndex(key, hashOf(key))) + if (entry != null && entry.value != None) { + val res = entry.value + deleteSlot(entry) res } else None } @@ -249,7 +274,7 @@ extends AbstractMap[Key, Value] } override def retain(f : (Key, Value) => Boolean) = { - foreachUndeletedEntry(entry => if (!f(entry.key, entry.value.get)) {entry.value = None; size -= 1; deleted += 1} ) + foreachUndeletedEntry(entry => if (!f(entry.key, entry.value.get)) deleteSlot(entry)) this } diff --git a/test/junit/scala/collection/mutable/OpenHashMapTest.scala b/test/junit/scala/collection/mutable/OpenHashMapTest.scala index 9b5c20e01a78..b6cddf210111 100644 --- a/test/junit/scala/collection/mutable/OpenHashMapTest.scala +++ b/test/junit/scala/collection/mutable/OpenHashMapTest.scala @@ -4,6 +4,10 @@ import org.junit.Test import org.junit.Assert._ import org.junit.runner.RunWith import org.junit.runners.JUnit4 +import org.openjdk.jol.info.GraphLayout +import org.openjdk.jol.info.GraphWalker +import org.openjdk.jol.info.GraphVisitor +import org.openjdk.jol.info.GraphPathRecord /** Tests for [[OpenHashMap]]. */ @RunWith(classOf[JUnit4]) @@ -28,7 +32,13 @@ class OpenHashMapTest { val fieldMirror = mirror.reflect(m).reflectField(termSym) */ // Use Java reflection instead for now. - val field = m.getClass.getDeclaredField("deleted") + val field = + try { // Name may or not be mangled, depending on what the compiler authors are doing. + m.getClass.getDeclaredField("scala$collection$mutable$OpenHashMap$$deleted") + } catch { + case _: NoSuchFieldException => + m.getClass.getDeclaredField("deleted") + } field.setAccessible(true) m.put(0, 0) @@ -39,4 +49,50 @@ class OpenHashMapTest { // TODO assertEquals(0, fieldMirror.get.asInstanceOf[Int]) assertEquals(0, field.getInt(m)) } + + /** Test that an [[OpenHashMap]] frees references to a deleted key (SI-9522). */ + @Test + def freesDeletedKey { + import scala.language.reflectiveCalls + + class MyClass { + override def hashCode() = 42 + } + + val counter = new GraphVisitor() { + private[this] var instanceCount: Int = _ + + def countInstances(obj: AnyRef) = { + instanceCount = 0 + val walker = new GraphWalker(obj) + walker.addVisitor(this) + walker.walk + instanceCount + } + + override def visit(record: GraphPathRecord) { + if (record.klass() == classOf[MyClass]) instanceCount += 1 + } + } + + val m = OpenHashMap.empty[MyClass, Int] + val obj = new MyClass + assertEquals("Found a key instance in the map before adding one!?", 0, counter.countInstances(m)) + m.put(obj, 0) + assertEquals("There should be only one key instance in the map.", 1, counter.countInstances(m)) + m.put(obj, 1) + assertEquals("There should still be only one key instance in the map.", 1, counter.countInstances(m)) + m.remove(obj) + assertEquals("There should be no key instance in the map.", 0, counter.countInstances(m)) + + val obj2 = new MyClass + assertEquals("The hash codes of the test objects need to match.", obj.##, obj2.##) + m.put(obj, 0) + m.put(obj2, 0) + assertEquals("There should be two key instances in the map.", 2, counter.countInstances(m)) + m.remove(obj) + assertEquals("There should be one key instance in the map.", 1, counter.countInstances(m)) + m.remove(obj2) + assertEquals("There should be no key instance in the map.", 0, counter.countInstances(m)) + } } From dd3a90e939fef264292b3dbc75d0cdbce4eeae6f Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Tue, 24 May 2016 21:12:20 +0100 Subject: [PATCH 059/153] Fix Scaladoc link syntax on java.util.Formatter references --- src/library/scala/Predef.scala | 3 +-- src/library/scala/collection/immutable/StringLike.scala | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 58d43f866616..216f6663b5d5 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -388,8 +388,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { * based on a string pattern (in a fashion similar to printf in C). * * The interpretation of the formatting patterns is described in - * - * `java.util.Formatter`. + * [[java.util.Formatter]]. * * Consider using the [[scala.StringContext.f f interpolator]] as more type safe and idiomatic. * diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index 8a9df0e8625d..3c7507f480da 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -336,8 +336,7 @@ self => * holes. * * The interpretation of the formatting patterns is described in - * - * `java.util.Formatter`, with the addition that + * [[java.util.Formatter]], with the addition that * classes deriving from `ScalaNumber` (such as [[scala.BigInt]] and * [[scala.BigDecimal]]) are unwrapped to pass a type which `Formatter` * understands. @@ -352,8 +351,7 @@ self => * which influences formatting as in `java.lang.String`'s format. * * The interpretation of the formatting patterns is described in - * - * `java.util.Formatter`, with the addition that + * [[java.util.Formatter]], with the addition that * classes deriving from `ScalaNumber` (such as `scala.BigInt` and * `scala.BigDecimal`) are unwrapped to pass a type which `Formatter` * understands. From 1db58b52e064579e857260de93e1a706a783a7e5 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 24 May 2016 22:13:20 +0200 Subject: [PATCH 060/153] Debug flag to print a summary of the inliner's work Example output below. Note that inlining List.map fails because the trait forwarder uses `INVOKESPECIAL` for now, will change with pr 5177. $ cat Test.scala class C { def foo = Map(1 -> 'a', 2 -> 'b') def bar(l: List[Int]) = l.map(_ + 1) } $ qsc -Yopt-log-inline _ -Yopt:l:classpath Test.scala Inlining into C.foo (initially 36 instructions, ultimately 72): - Inlined scala/Predef$ArrowAssoc$.$minus$greater$extension (8 instructions) 2 times: the callee is annotated `@inline` Inlining into C.bar (initially 12 instructions, ultimately 12): - Failed to inline scala/collection/immutable/List.map (the callee is a higher-order method, the argument for parameter (bf: Function1) is a function literal): The callee scala/collection/immutable/List::map(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object; contains the instruction INVOKESPECIAL scala/collection/TraversableLike.map (Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object; that would cause an IllegalAccessError when inlined into class C. --- .../tools/nsc/backend/jvm/opt/Inliner.scala | 38 ++++++++++++++- .../backend/jvm/opt/InlinerHeuristics.scala | 48 +++++++++++++++---- .../tools/nsc/backend/jvm/opt/LocalOpt.scala | 3 +- .../tools/nsc/settings/ScalaSettings.scala | 4 +- .../scala/tools/nsc/util/StackTracing.scala | 2 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 10 ++-- 6 files changed, 87 insertions(+), 18 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index f35eaa45e927..4b65a566d3ec 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -25,6 +25,9 @@ class Inliner[BT <: BTypes](val btypes: BT) { import inlinerHeuristics._ import backendUtils._ + case class InlineLog(request: InlineRequest, sizeBefore: Int, sizeAfter: Int, sizeInlined: Int, warning: Option[CannotInlineWarning]) + var inlineLog: List[InlineLog] = Nil + def runInliner(): Unit = { for (request <- collectAndOrderInlineRequests) { val Right(callee) = request.callsite.callee // collectAndOrderInlineRequests returns callsites with a known callee @@ -42,6 +45,29 @@ class Inliner[BT <: BTypes](val btypes: BT) { } } } + + if (compilerSettings.YoptLogInline.isSetByUser) { + val methodPrefix = { val p = compilerSettings.YoptLogInline.value; if (p == "_") "" else p } + val byCallsiteMethod = inlineLog.groupBy(_.request.callsite.callsiteMethod).toList.sortBy(_._2.head.request.callsite.callsiteClass.internalName) + for ((m, mLogs) <- byCallsiteMethod) { + val initialSize = mLogs.minBy(_.sizeBefore).sizeBefore + val firstLog = mLogs.head + val methodName = s"${firstLog.request.callsite.callsiteClass.internalName}.${m.name}" + if (methodName.startsWith(methodPrefix)) { + println(s"Inlining into $methodName (initially $initialSize instructions, ultimately ${m.instructions.size}):") + val byCallee = mLogs.groupBy(_.request.callsite.callee.get).toList.sortBy(_._2.length).reverse + for ((c, cLogs) <- byCallee) { + val first = cLogs.head + if (first.warning.isEmpty) { + val num = if (cLogs.tail.isEmpty) "" else s" ${cLogs.length} times" + println(s" - Inlined ${c.calleeDeclarationClass.internalName}.${c.callee.name} (${first.sizeInlined} instructions)$num: ${first.request.reason}") + } else + println(s" - Failed to inline ${c.calleeDeclarationClass.internalName}.${c.callee.name} (${first.request.reason}): ${first.warning.get}") + } + println() + } + } + } } /** @@ -184,7 +210,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { def impl(post: InlineRequest, at: Callsite): List[InlineRequest] = { post.callsite.inlinedClones.find(_.clonedWhenInlining == at) match { case Some(clonedCallsite) => - List(InlineRequest(clonedCallsite.callsite, post.post)) + List(InlineRequest(clonedCallsite.callsite, post.post, post.reason)) case None => post.post.flatMap(impl(_, post.callsite)).flatMap(impl(_, at)) } @@ -199,9 +225,17 @@ class Inliner[BT <: BTypes](val btypes: BT) { * @return An inliner warning for each callsite that could not be inlined. */ def inline(request: InlineRequest): List[CannotInlineWarning] = canInlineBody(request.callsite) match { - case Some(w) => List(w) + case Some(w) => + if (compilerSettings.YoptLogInline.isSetByUser) { + val size = request.callsite.callsiteMethod.instructions.size + inlineLog ::= InlineLog(request, size, size, 0, Some(w)) + } + List(w) case None => + val sizeBefore = request.callsite.callsiteMethod.instructions.size inlineCallsite(request.callsite) + if (compilerSettings.YoptLogInline.isSetByUser) + inlineLog ::= InlineLog(request, sizeBefore, request.callsite.callsiteMethod.instructions.size, request.callsite.callee.get.callee.instructions.size, None) val postRequests = request.post.flatMap(adaptPostRequestForMainCallsite(_, request.callsite)) postRequests flatMap inline } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala index 6aaf9734d381..fd65b7176299 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala @@ -17,7 +17,7 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { import inliner._ import callGraph._ - case class InlineRequest(callsite: Callsite, post: List[InlineRequest]) { + case class InlineRequest(callsite: Callsite, post: List[InlineRequest], reason: String) { // invariant: all post inline requests denote callsites in the callee of the main callsite for (pr <- post) assert(pr.callsite.callsiteMethod == callsite.callee.get.callee, s"Callsite method mismatch: main $callsite - post ${pr.callsite}") } @@ -40,7 +40,7 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { var requests = Set.empty[InlineRequest] callGraph.callsites(methodNode).valuesIterator foreach { case callsite @ Callsite(_, _, _, Right(Callee(callee, calleeDeclClass, safeToInline, canInlineFromSource, calleeAnnotatedInline, _, _, callsiteWarning)), _, _, _, pos, _, _) => - inlineRequest(callsite) match { + inlineRequest(callsite, requests) match { case Some(Right(req)) => requests += req case Some(Left(w)) => if ((calleeAnnotatedInline && bTypes.compilerSettings.YoptWarningEmitAtInlineFailed) || w.emitWarning(compilerSettings)) { @@ -87,20 +87,29 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { * InlineRequest for the original callsite? new subclass of OptimizerWarning. * `Some(Right)` if the callsite should be and can be inlined */ - def inlineRequest(callsite: Callsite): Option[Either[OptimizerWarning, InlineRequest]] = { + def inlineRequest(callsite: Callsite, selectedRequestsForCallee: Set[InlineRequest]): Option[Either[OptimizerWarning, InlineRequest]] = { val callee = callsite.callee.get - def requestIfCanInline(callsite: Callsite): Either[OptimizerWarning, InlineRequest] = inliner.earlyCanInlineCheck(callsite) match { + def requestIfCanInline(callsite: Callsite, reason: String): Either[OptimizerWarning, InlineRequest] = inliner.earlyCanInlineCheck(callsite) match { case Some(w) => Left(w) - case None => Right(InlineRequest(callsite, Nil)) + case None => Right(InlineRequest(callsite, Nil, reason)) } compilerSettings.YoptInlineHeuristics.value match { case "everything" => - if (callee.safeToInline) Some(requestIfCanInline(callsite)) + if (callee.safeToInline) { + val reason = if (compilerSettings.YoptLogInline.isSetByUser) "the inline strategy is \"everything\"" else null + Some(requestIfCanInline(callsite, reason)) + } else None case "at-inline-annotated" => - if (callee.safeToInline && callee.annotatedInline) Some(requestIfCanInline(callsite)) + if (callee.safeToInline && callee.annotatedInline) { + val reason = if (compilerSettings.YoptLogInline.isSetByUser) { + val what = if (callee.safeToInline) "callee" else "callsite" + s"the $what is annotated `@inline`" + } else null + Some(requestIfCanInline(callsite, reason)) + } else None case "default" => @@ -108,7 +117,30 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { def shouldInlineHO = callee.samParamTypes.nonEmpty && (callee.samParamTypes exists { case (index, _) => callsite.argInfos.contains(index) }) - if (callee.annotatedInline || callsite.annotatedInline || shouldInlineHO) Some(requestIfCanInline(callsite)) + if (callee.annotatedInline || callsite.annotatedInline || shouldInlineHO) { + val reason = if (compilerSettings.YoptLogInline.isSetByUser) { + if (callee.annotatedInline || callsite.annotatedInline) { + val what = if (callee.safeToInline) "callee" else "callsite" + s"the $what is annotated `@inline`" + } else { + val paramNames = Option(callee.callee.parameters).map(_.asScala.map(_.name).toVector) + def param(i: Int) = { + def syn = s"" + paramNames.fold(syn)(v => v.applyOrElse(i, (_: Int) => syn)) + } + def samInfo(i: Int, sam: String, arg: String) = s"the argument for parameter (${param(i)}: $sam) is a $arg" + val argInfos = for ((i, sam) <- callee.samParamTypes; info <- callsite.argInfos.get(i)) yield { + val argKind = info match { + case FunctionLiteral => "function literal" + case ForwardedParam(_) => "parameter of the callsite method" + } + samInfo(i, sam.internalName.split('/').last, argKind) + } + s"the callee is a higher-order method, ${argInfos.mkString(", ")}" + } + } else null + Some(requestIfCanInline(callsite, reason)) + } else None } else None } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala index 4e1349257e85..4972a49bb467 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala @@ -231,7 +231,8 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { // for local variables in dead blocks. Maybe that's a bug in the ASM framework. var currentTrace: String = null - val doTrace = compilerSettings.YoptTrace.isSetByUser && compilerSettings.YoptTrace.value == ownerClassName + "." + method.name + val methodPrefix = {val p = compilerSettings.YoptTrace.value; if (p == "_") "" else p } + val doTrace = compilerSettings.YoptTrace.isSetByUser && s"$ownerClassName.${method.name}".startsWith(methodPrefix) def traceIfChanged(optName: String): Unit = if (doTrace) { val after = AsmUtils.textify(method) if (currentTrace != after) { diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 9a0d86a94df1..aa43772dd774 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -302,7 +302,9 @@ trait ScalaSettings extends AbsScalaSettings def YoptWarningNoInlineMissingBytecode = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingBytecode) def YoptWarningNoInlineMissingScalaInlineInfoAttr = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingScalaInlineInfoAttr) - val YoptTrace = StringSetting("-Yopt-trace", "package/Class.method", "Trace the optimizer progress for a specific method.", "") + val YoptTrace = StringSetting("-Yopt-trace", "package/Class.method", "Trace the optimizer progress for methods; `_` to print all, prefix match to select.", "") + + val YoptLogInline = StringSetting("-Yopt-log-inline", "package/Class.method", "Print a summary of inliner activity; `_` to print all, prefix match to select.", "") private def removalIn212 = "This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug." diff --git a/src/compiler/scala/tools/nsc/util/StackTracing.scala b/src/compiler/scala/tools/nsc/util/StackTracing.scala index fa4fe29f2822..0765bb923f0d 100644 --- a/src/compiler/scala/tools/nsc/util/StackTracing.scala +++ b/src/compiler/scala/tools/nsc/util/StackTracing.scala @@ -19,7 +19,7 @@ private[util] trait StackTracing extends Any { def stackTracePrefixString(e: Throwable)(p: StackTraceElement => Boolean): String = { import collection.mutable.{ ArrayBuffer, ListBuffer } import compat.Platform.EOL - import util.Properties.isJavaAtLeast + import scala.util.Properties.isJavaAtLeast val sb = ListBuffer.empty[String] diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index fd020c7d9390..fb708c4f293b 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -72,7 +72,7 @@ class InlinerTest extends BytecodeTesting { def inlineTest(code: String, mod: ClassNode => Unit = _ => ()): MethodNode = { val (gMethod, fCall) = gMethAndFCallsite(code, mod) - inliner.inline(InlineRequest(fCall, Nil)) + inliner.inline(InlineRequest(fCall, Nil, null)) gMethod } @@ -343,7 +343,7 @@ class InlinerTest extends BytecodeTesting { val warning = inliner.canInlineBody(call) assert(warning.isEmpty, warning) - inliner.inline(InlineRequest(call, Nil)) + inliner.inline(InlineRequest(call, Nil, null)) val ins = instructionsFromMethod(fMeth) // no invocations, lowestOneBit is inlined @@ -976,7 +976,7 @@ class InlinerTest extends BytecodeTesting { inliner.inline(InlineRequest(hCall, post = List(InlineRequest(gCall, - post = List(InlineRequest(fCall, Nil)))))) + post = List(InlineRequest(fCall, Nil, null)), null)), null)) assertNoInvoke(convertMethod(iMeth)) // no invoke in i: first h is inlined, then the inlined call to g is also inlined, etc for f assertInvoke(convertMethod(gMeth), "C", "f") // g itself still has the call to f } @@ -998,11 +998,11 @@ class InlinerTest extends BytecodeTesting { val bCall = getCallsite(c, "b") val cCall = getCallsite(d, "c") - inliner.inline(InlineRequest(bCall, Nil)) + inliner.inline(InlineRequest(bCall, Nil, null)) val req = InlineRequest(cCall, List(InlineRequest(bCall, - List(InlineRequest(aCall, Nil))))) + List(InlineRequest(aCall, Nil, null)), null)), null) inliner.inline(req) assertNoInvoke(convertMethod(d)) From 450df0e4225da325b1a68461d8eb852bc1e61cbc Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Wed, 25 May 2016 11:03:47 +0100 Subject: [PATCH 061/153] Use full braces style in AnsiColor example This matches the use of ${..} in Console. --- src/library/scala/io/AnsiColor.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/io/AnsiColor.scala b/src/library/scala/io/AnsiColor.scala index 720049ba8e10..df589bc66c0d 100644 --- a/src/library/scala/io/AnsiColor.scala +++ b/src/library/scala/io/AnsiColor.scala @@ -13,7 +13,7 @@ package io * * object ColorDemo extends App { * - * println(s"$REVERSED${BOLD}Hello 1979!$RESET") + * println(s"${REVERSED}${BOLD}Hello 1979!${RESET}") * } * }}} * From b85c9a722ce56ebfb6e41cea7a7387126286b187 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 25 May 2016 16:42:19 +0200 Subject: [PATCH 062/153] Rename -Yopt to -opt, -Yopt-warnings to -opt-warnings Keep -Yopt-inline-heuristics and -Yopt-trace unchanged --- build-ant-macros.xml | 2 +- build.xml | 8 +- project/ScalaOptionParser.scala | 2 +- scripts/jobs/integrate/bootstrap | 6 +- scripts/jobs/validate/test | 2 +- src/compiler/scala/tools/nsc/Reporting.scala | 2 +- .../nsc/backend/jvm/BCodeIdiomatic.scala | 2 +- .../scala/tools/nsc/backend/jvm/BTypes.scala | 2 +- .../nsc/backend/jvm/BTypesFromSymbols.scala | 2 +- .../nsc/backend/jvm/BackendReporting.scala | 24 +++--- .../tools/nsc/backend/jvm/GenBCode.scala | 8 +- .../tools/nsc/backend/jvm/opt/CallGraph.scala | 4 +- .../backend/jvm/opt/ClosureOptimizer.scala | 2 +- .../tools/nsc/backend/jvm/opt/Inliner.scala | 2 +- .../backend/jvm/opt/InlinerHeuristics.scala | 6 +- .../tools/nsc/backend/jvm/opt/LocalOpt.scala | 32 +++---- .../tools/nsc/settings/ScalaSettings.scala | 84 +++++++++---------- .../instrumented/inline-in-constructors.flags | 2 +- test/files/jvm/bytecode-test-example.flags | 2 +- test/files/jvm/unreachable/Foo_1.flags | 2 +- test/files/neg/inlineIndyLambdaPrivate.flags | 2 +- test/files/neg/inlineMaxSize.flags | 2 +- test/files/neg/optimiseDeprecated.check | 2 +- test/files/neg/partestInvalidFlag.check | 4 +- test/files/neg/partestInvalidFlag.flags | 2 +- test/files/neg/sealed-final-neg.flags | 2 +- test/files/pos/inline-access-levels.flags | 2 +- test/files/pos/t3234.flags | 2 +- test/files/pos/t3420.flags | 2 +- test/files/pos/t4840.flags | 2 +- test/files/pos/t8410.flags | 2 +- test/files/pos/t9111-inliner-workaround.flags | 2 +- test/files/run/bcodeInlinerMixed.flags | 2 +- test/files/run/classfile-format-51.scala | 2 +- test/files/run/classfile-format-52.scala | 2 +- test/files/run/finalvar.flags | 2 +- test/files/run/icode-reader-dead-code.scala | 2 +- test/files/run/noInlineUnknownIndy/Test.scala | 2 +- test/files/run/nothingTypeDce.flags | 2 +- test/files/run/nothingTypeDce.scala | 2 +- test/files/run/nothingTypeNoOpt.flags | 2 +- test/files/run/nothingTypeNoOpt.scala | 2 +- test/files/run/synchronized.flags | 2 +- test/files/run/t2106.flags | 2 +- test/files/run/t3509.flags | 2 +- test/files/run/t3569.flags | 2 +- test/files/run/t4285.flags | 2 +- test/files/run/t4935.flags | 2 +- test/files/run/t5789.scala | 2 +- test/files/run/t6102.flags | 2 +- test/files/run/t6188.flags | 2 +- test/files/run/t7407.flags | 2 +- test/files/run/t7459b-optimize.flags | 2 +- test/files/run/t7582.flags | 2 +- test/files/run/t7582b.flags | 2 +- test/files/run/t7852.flags | 2 +- test/files/run/t8601-closure-elim.flags | 2 +- test/files/run/t8601.flags | 2 +- test/files/run/t8601b.flags | 2 +- test/files/run/t8601c.flags | 2 +- test/files/run/t8601d.flags | 2 +- test/files/run/t8601e.flags | 2 +- test/files/run/t8925.flags | 2 +- test/files/run/t9003.flags | 2 +- test/files/run/t9403.flags | 2 +- .../tools/nsc/backend/jvm/BTypesTest.scala | 2 +- .../nsc/backend/jvm/DirectCompileTest.scala | 2 +- .../backend/jvm/OptimizedBytecodeTest.scala | 2 +- .../jvm/analysis/NullnessAnalyzerTest.scala | 2 +- .../jvm/analysis/ProdConsAnalyzerTest.scala | 2 +- .../nsc/backend/jvm/opt/AnalyzerTest.scala | 2 +- .../jvm/opt/BTypesFromClassfileTest.scala | 2 +- .../nsc/backend/jvm/opt/CallGraphTest.scala | 2 +- .../jvm/opt/ClosureOptimizerTest.scala | 2 +- .../jvm/opt/CompactLocalVariablesTest.scala | 4 +- .../jvm/opt/EmptyExceptionHandlersTest.scala | 4 +- .../nsc/backend/jvm/opt/InlineInfoTest.scala | 2 +- .../backend/jvm/opt/InlineWarningTest.scala | 10 +-- .../jvm/opt/InlinerIllegalAccessTest.scala | 2 +- .../opt/InlinerSeparateCompilationTest.scala | 4 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 8 +- .../backend/jvm/opt/MethodLevelOptsTest.scala | 2 +- .../backend/jvm/opt/ScalaInlineInfoTest.scala | 2 +- .../backend/jvm/opt/UnreachableCodeTest.scala | 6 +- .../jvm/opt/UnusedLocalVariablesTest.scala | 2 +- .../transform/patmat/PatmatBytecodeTest.scala | 2 +- .../jvm/constant-optimization/Foo_1.flags | 2 +- 87 files changed, 178 insertions(+), 178 deletions(-) diff --git a/build-ant-macros.xml b/build-ant-macros.xml index 19429cdaa3f5..e077cfbb4c88 100644 --- a/build-ant-macros.xml +++ b/build-ant-macros.xml @@ -6,7 +6,7 @@ - + diff --git a/build.xml b/build.xml index c1b0b228a1f9..50ced2424718 100644 --- a/build.xml +++ b/build.xml @@ -19,7 +19,7 @@ ant $antArgs $scalacArgs $targets antArgs tend to be: -Darchives.skipxz=true - -Dscalac.args.optimise=-Yopt:l:classpath + -Dscalac.args.optimise=-opt:l:classpath scalacArgs examples: "-Dscalac.args=\"-Yrangepos\" -Dpartest.scalac_opts=\"-Yrangepos\"" @@ -79,13 +79,13 @@ TODO: - + - + @@ -1043,7 +1043,7 @@ TODO: - + diff --git a/project/ScalaOptionParser.scala b/project/ScalaOptionParser.scala index f2fd4d86d7c0..82b8f5762c57 100644 --- a/project/ScalaOptionParser.scala +++ b/project/ScalaOptionParser.scala @@ -108,7 +108,7 @@ object ScalaOptionParser { private def multiChoiceSettingNames = Map[String, List[String]]( "-Xlint" -> List("adapted-args", "nullary-unit", "inaccessible", "nullary-override", "infer-any", "missing-interpolator", "doc-detached", "private-shadow", "type-parameter-shadow", "poly-implicit-overload", "option-implicit", "delayedinit-select", "by-name-right-associative", "package-object-classes", "unsound-match", "stars-align"), "-language" -> List("help", "_", "dynamics", "postfixOps", "reflectiveCalls", "implicitConversions", "higherKinds", "existentials", "experimental.macros"), - "-Yopt" -> List("l:none", "l:default", "l:method", "l:project", "l:classpath", "unreachable-code", "simplify-jumps", "empty-line-numbers", "empty-labels", "compact-locals", "nullness-tracking", "closure-elimination", "inline-project", "inline-global"), + "-opt" -> List("l:none", "l:default", "l:method", "l:project", "l:classpath", "unreachable-code", "simplify-jumps", "empty-line-numbers", "empty-labels", "compact-locals", "nullness-tracking", "closure-elimination", "inline-project", "inline-global"), "-Ystatistics" -> List("parser", "typer", "patmat", "erasure", "cleanup", "jvm") ) private def scalaVersionSettings = List("-Xmigration", "-Xsource") diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index 65758ea528c4..05c7d22b26b4 100644 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -494,7 +494,7 @@ bootstrap() { -Dremote.snapshot.repository=NOPE\ -Dremote.release.repository=$releaseTempRepoUrl\ -Drepository.credentials.id=$releaseTempRepoCred\ - -Dscalac.args.optimise=-Yopt:l:classpath\ + -Dscalac.args.optimise=-opt:l:classpath\ -Ddocs.skip=1\ -Dlocker.skip=1\ $publishStarrPrivateTask >> $baseDir/logs/builds 2>&1 @@ -516,7 +516,7 @@ bootstrap() { $SET_STARR\ -Dremote.release.repository=$releaseTempRepoUrl\ -Drepository.credentials.id=$releaseTempRepoCred\ - -Dscalac.args.optimise=-Yopt:l:classpath\ + -Dscalac.args.optimise=-opt:l:classpath\ -Ddocs.skip=1\ -Dlocker.skip=1\ $publishLockerPrivateTask >> $baseDir/logs/builds 2>&1 @@ -555,7 +555,7 @@ bootstrap() { -Dremote.snapshot.repository=NOPE\ -Dremote.release.repository=$releaseTempRepoUrl\ -Drepository.credentials.id=$releaseTempRepoCred\ - -Dscalac.args.optimise=-Yopt:l:classpath\ + -Dscalac.args.optimise=-opt:l:classpath\ $antBuildTask $publishPrivateTask # clear ivy cache (and to be sure, local as well), so the next round of sbt builds sees the fresh scala diff --git a/scripts/jobs/validate/test b/scripts/jobs/validate/test index d63d39c65d35..7c7024e87c9b 100755 --- a/scripts/jobs/validate/test +++ b/scripts/jobs/validate/test @@ -10,7 +10,7 @@ case $prDryRun in # build quick using STARR built upstream, as specified by scalaVersion # (in that sense it's locker, since it was built with starr by that upstream job) ant -Dstarr.version=$scalaVersion \ - -Dscalac.args.optimise=-Yopt:l:classpath \ + -Dscalac.args.optimise=-opt:l:classpath \ -Dlocker.skip=1 -Dextra.repo.url=$prRepoUrl \ $testExtraArgs ${testTarget-test.core docs.done} ;; diff --git a/src/compiler/scala/tools/nsc/Reporting.scala b/src/compiler/scala/tools/nsc/Reporting.scala index 5bdbf4bb6a63..8d0aedc76db8 100644 --- a/src/compiler/scala/tools/nsc/Reporting.scala +++ b/src/compiler/scala/tools/nsc/Reporting.scala @@ -49,7 +49,7 @@ trait Reporting extends scala.reflect.internal.Reporting { self: ast.Positions w private val _deprecationWarnings = new ConditionalWarning("deprecation", settings.deprecation) private val _uncheckedWarnings = new ConditionalWarning("unchecked", settings.unchecked) private val _featureWarnings = new ConditionalWarning("feature", settings.feature) - private val _inlinerWarnings = new ConditionalWarning("inliner", () => !settings.YoptWarningsSummaryOnly, settings.YoptWarnings) + private val _inlinerWarnings = new ConditionalWarning("inliner", () => !settings.optWarningsSummaryOnly, settings.optWarnings) private val _allConditionalWarnings = List(_deprecationWarnings, _uncheckedWarnings, _featureWarnings, _inlinerWarnings) // TODO: remove in favor of the overload that takes a Symbol, give that argument a default (NoSymbol) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala index 0a95bc5e3998..ed1b4ec3255e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala @@ -392,7 +392,7 @@ abstract class BCodeIdiomatic extends SubComponent { private def addInvoke(opcode: Int, owner: String, name: String, desc: String, itf: Boolean, pos: Position) = { val node = new MethodInsnNode(opcode, owner, name, desc, itf) jmethod.instructions.add(node) - if (settings.YoptInlinerEnabled) callsitePositions(node) = pos + if (settings.optInlinerEnabled) callsitePositions(node) = pos } final def invokedynamic(owner: String, name: String, desc: String) { jmethod.visitMethodInsn(Opcodes.INVOKEDYNAMIC, owner, name, desc) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index 2637d2105032..a708feb0a7b8 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -271,7 +271,7 @@ abstract class BTypes { // The InlineInfo is built from the classfile (not from the symbol) for all classes that are NOT // being compiled. For those classes, the info is only needed if the inliner is enabled, othewise // we can save the memory. - if (!compilerSettings.YoptInlinerEnabled) BTypes.EmptyInlineInfo + if (!compilerSettings.optInlinerEnabled) BTypes.EmptyInlineInfo else fromClassfileAttribute getOrElse fromClassfileWithoutAttribute } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index d10b6c8dbaf6..d83b4a1d856e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -514,7 +514,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { // enclosingTopLevelClass is being compiled. after flatten, all classes are considered top-level, // so `compiles` would return `false`. if (exitingPickler(currentRun.compiles(classSym))) buildFromSymbol // InlineInfo required for classes being compiled, we have to create the classfile attribute - else if (!compilerSettings.YoptInlinerEnabled) BTypes.EmptyInlineInfo // For other classes, we need the InlineInfo only inf the inliner is enabled. + else if (!compilerSettings.optInlinerEnabled) BTypes.EmptyInlineInfo // For other classes, we need the InlineInfo only inf the inliner is enabled. else { // For classes not being compiled, the InlineInfo is read from the classfile attribute. This // fixes an issue with mixed-in methods: the mixin phase enters mixin methods only to class diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala index 4287c24dc806..4ad4a9572844 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala @@ -117,15 +117,15 @@ object BackendReporting { def emitWarning(settings: ScalaSettings): Boolean = this match { case ClassNotFound(_, javaDefined) => - if (javaDefined) settings.YoptWarningNoInlineMixed - else settings.YoptWarningNoInlineMissingBytecode + if (javaDefined) settings.optWarningNoInlineMixed + else settings.optWarningNoInlineMissingBytecode case m @ MethodNotFound(_, _, _, missing) => if (m.isArrayMethod) false - else settings.YoptWarningNoInlineMissingBytecode || missing.exists(_.emitWarning(settings)) + else settings.optWarningNoInlineMissingBytecode || missing.exists(_.emitWarning(settings)) case FieldNotFound(_, _, _, missing) => - settings.YoptWarningNoInlineMissingBytecode || missing.exists(_.emitWarning(settings)) + settings.optWarningNoInlineMissingBytecode || missing.exists(_.emitWarning(settings)) } } @@ -146,7 +146,7 @@ object BackendReporting { def emitWarning(settings: ScalaSettings): Boolean = this match { case NoClassBTypeInfoMissingBytecode(cause) => cause.emitWarning(settings) - case NoClassBTypeInfoClassSymbolInfoFailedSI9111(_) => settings.YoptWarningNoInlineMissingBytecode + case NoClassBTypeInfoClassSymbolInfoFailedSI9111(_) => settings.optWarningNoInlineMissingBytecode } } @@ -179,7 +179,7 @@ object BackendReporting { case MethodInlineInfoIncomplete(_, _, _, cause) => cause.emitWarning(settings) case MethodInlineInfoMissing(_, _, _, Some(cause)) => cause.emitWarning(settings) - case MethodInlineInfoMissing(_, _, _, None) => settings.YoptWarningNoInlineMissingBytecode + case MethodInlineInfoMissing(_, _, _, None) => settings.optWarningNoInlineMissingBytecode case MethodInlineInfoError(_, _, _, cause) => cause.emitWarning(settings) } @@ -225,7 +225,7 @@ object BackendReporting { def emitWarning(settings: ScalaSettings): Boolean = this match { case _: IllegalAccessInstruction | _: MethodWithHandlerCalledOnNonEmptyStack | _: SynchronizedMethod | _: StrictfpMismatch | _: ResultingMethodTooLarge => - settings.YoptWarnings.contains(settings.YoptWarningsChoices.anyInlineFailed) + settings.optWarnings.contains(settings.optWarningsChoices.anyInlineFailed) case IllegalAccessCheckFailed(_, _, _, _, _, cause) => cause.emitWarning(settings) @@ -247,7 +247,7 @@ object BackendReporting { // but at the place where it's created (in findIllegalAccess) we don't have the necessary data (calleeName, calleeDescriptor). case object UnknownInvokeDynamicInstruction extends OptimizerWarning { override def toString = "The callee contains an InvokeDynamic instruction with an unknown bootstrap method (not a LambdaMetaFactory)." - def emitWarning(settings: ScalaSettings): Boolean = settings.YoptWarnings.contains(settings.YoptWarningsChoices.anyInlineFailed) + def emitWarning(settings: ScalaSettings): Boolean = settings.optWarnings.contains(settings.optWarningsChoices.anyInlineFailed) } /** @@ -259,7 +259,7 @@ object BackendReporting { override def emitWarning(settings: ScalaSettings): Boolean = this match { case RewriteClosureAccessCheckFailed(_, cause) => cause.emitWarning(settings) - case RewriteClosureIllegalAccess(_, _) => settings.YoptWarnings.contains(settings.YoptWarningsChoices.anyInlineFailed) + case RewriteClosureIllegalAccess(_, _) => settings.optWarnings.contains(settings.optWarningsChoices.anyInlineFailed) } override def toString: String = this match { @@ -291,10 +291,10 @@ object BackendReporting { } def emitWarning(settings: ScalaSettings): Boolean = this match { - case NoInlineInfoAttribute(_) => settings.YoptWarningNoInlineMissingScalaInlineInfoAttr + case NoInlineInfoAttribute(_) => settings.optWarningNoInlineMissingScalaInlineInfoAttr case ClassNotFoundWhenBuildingInlineInfoFromSymbol(cause) => cause.emitWarning(settings) - case ClassSymbolInfoFailureSI9111(_) => settings.YoptWarningNoInlineMissingBytecode - case UnknownScalaInlineInfoVersion(_, _) => settings.YoptWarningNoInlineMissingScalaInlineInfoAttr + case ClassSymbolInfoFailureSI9111(_) => settings.optWarningNoInlineMissingBytecode + case UnknownScalaInlineInfoVersion(_, _) => settings.optWarningNoInlineMissingScalaInlineInfoAttr } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala index 3520d5759941..02dc2b8edea2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala @@ -225,19 +225,19 @@ abstract class GenBCode extends BCodeSyncAndTry { // add classes to the bytecode repo before building the call graph: the latter needs to // look up classes and methods in the code repo. - if (settings.YoptAddToBytecodeRepository) q2.asScala foreach { + if (settings.optAddToBytecodeRepository) q2.asScala foreach { case Item2(_, mirror, plain, bean, _) => if (mirror != null) byteCodeRepository.add(mirror, ByteCodeRepository.CompilationUnit) if (plain != null) byteCodeRepository.add(plain, ByteCodeRepository.CompilationUnit) if (bean != null) byteCodeRepository.add(bean, ByteCodeRepository.CompilationUnit) } - if (settings.YoptBuildCallGraph) q2.asScala foreach { item => + if (settings.optBuildCallGraph) q2.asScala foreach { item => // skip call graph for mirror / bean: wd don't inline into tem, and they are not used in the plain class if (item.plain != null) callGraph.addClass(item.plain) } - if (settings.YoptInlinerEnabled) + if (settings.optInlinerEnabled) bTypes.inliner.runInliner() - if (settings.YoptClosureInvocations) + if (settings.optClosureInvocations) closureOptimizer.rewriteClosureApplyInvocations() } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index d241acf7b1cc..e8d1bf203a42 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -102,7 +102,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // It is also used to get the stack height at the call site. val analyzer = { - if (compilerSettings.YoptNullnessTracking && AsmAnalyzer.sizeOKForNullness(methodNode)) { + if (compilerSettings.optNullnessTracking && AsmAnalyzer.sizeOKForNullness(methodNode)) { Some(new AsmAnalyzer(methodNode, definingClass.internalName, new NullnessAnalyzer(btypes))) } else if (AsmAnalyzer.sizeOKForBasicValue(methodNode)) { Some(new AsmAnalyzer(methodNode, definingClass.internalName)) @@ -273,7 +273,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // callee, we only check there for the methodInlineInfo, we should find it there. calleeDeclarationClassBType.info.orThrow.inlineInfo.methodInfos.get(methodSignature) match { case Some(methodInlineInfo) => - val canInlineFromSource = compilerSettings.YoptInlineGlobal || calleeSource == CompilationUnit + val canInlineFromSource = compilerSettings.optInlineGlobal || calleeSource == CompilationUnit val isAbstract = BytecodeUtils.isAbstractMethod(calleeMethodNode) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala index 93dc40f318c0..7f9858286eae 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala @@ -358,7 +358,7 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) { val callee = bodyMethod.map({ case (bodyMethodNode, bodyMethodDeclClass) => val bodyDeclClassType = classBTypeFromParsedClassfile(bodyMethodDeclClass) - val canInlineFromSource = compilerSettings.YoptInlineGlobal || bodyMethodIsBeingCompiled + val canInlineFromSource = compilerSettings.optInlineGlobal || bodyMethodIsBeingCompiled Callee( callee = bodyMethodNode, calleeDeclarationClass = bodyDeclClassType, diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index f35eaa45e927..9660d878eb26 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -35,7 +35,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { val warnings = inline(request) for (warning <- warnings) { - if ((callee.annotatedInline && btypes.compilerSettings.YoptWarningEmitAtInlineFailed) || warning.emitWarning(compilerSettings)) { + if ((callee.annotatedInline && btypes.compilerSettings.optWarningEmitAtInlineFailed) || warning.emitWarning(compilerSettings)) { val annotWarn = if (callee.annotatedInline) " is annotated @inline but" else "" val msg = s"${BackendReporting.methodSignature(callee.calleeDeclarationClass.internalName, callee.callee)}$annotWarn could not be inlined:\n$warning" backendReporting.inlinerWarning(request.callsite.callsitePosition, msg) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala index 6aaf9734d381..d39db4d3b121 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala @@ -43,16 +43,16 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { inlineRequest(callsite) match { case Some(Right(req)) => requests += req case Some(Left(w)) => - if ((calleeAnnotatedInline && bTypes.compilerSettings.YoptWarningEmitAtInlineFailed) || w.emitWarning(compilerSettings)) { + if ((calleeAnnotatedInline && bTypes.compilerSettings.optWarningEmitAtInlineFailed) || w.emitWarning(compilerSettings)) { val annotWarn = if (calleeAnnotatedInline) " is annotated @inline but" else "" val msg = s"${BackendReporting.methodSignature(calleeDeclClass.internalName, callee)}$annotWarn could not be inlined:\n$w" backendReporting.inlinerWarning(callsite.callsitePosition, msg) } case None => - if (canInlineFromSource && calleeAnnotatedInline && !callsite.annotatedNoInline && bTypes.compilerSettings.YoptWarningEmitAtInlineFailed) { + if (canInlineFromSource && calleeAnnotatedInline && !callsite.annotatedNoInline && bTypes.compilerSettings.optWarningEmitAtInlineFailed) { // if the callsite is annotated @inline, we report an inline warning even if the underlying - // reason is, for example, mixed compilation (which has a separate -Yopt-warning flag). + // reason is, for example, mixed compilation (which has a separate -opt-warning flag). def initMsg = s"${BackendReporting.methodSignature(calleeDeclClass.internalName, callee)} is annotated @inline but cannot be inlined" def warnMsg = callsiteWarning.map(" Possible reason:\n" + _).getOrElse("") if (!safeToInline) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala index 4e1349257e85..17490862c82e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala @@ -191,7 +191,7 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { * @return `true` if unreachable code was eliminated in some method, `false` otherwise. */ def methodOptimizations(clazz: ClassNode): Boolean = { - !compilerSettings.YoptNone && clazz.methods.asScala.foldLeft(false) { + !compilerSettings.optNone && clazz.methods.asScala.foldLeft(false) { case (changed, method) => methodOptimizations(method, clazz.name) || changed } } @@ -261,46 +261,46 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { traceIfChanged("beforeMethodOpt") // NULLNESS OPTIMIZATIONS - val runNullness = compilerSettings.YoptNullnessTracking && requestNullness + val runNullness = compilerSettings.optNullnessTracking && requestNullness val nullnessOptChanged = runNullness && nullnessOptimizations(method, ownerClassName) traceIfChanged("nullness") // UNREACHABLE CODE // Both AliasingAnalyzer (used in copyProp) and ProdConsAnalyzer (used in eliminateStaleStores, // boxUnboxElimination) require not having unreachable instructions (null frames). - val runDCE = (compilerSettings.YoptUnreachableCode && (requestDCE || nullnessOptChanged)) || - compilerSettings.YoptBoxUnbox || - compilerSettings.YoptCopyPropagation + val runDCE = (compilerSettings.optUnreachableCode && (requestDCE || nullnessOptChanged)) || + compilerSettings.optBoxUnbox || + compilerSettings.optCopyPropagation val (codeRemoved, liveLabels) = if (runDCE) removeUnreachableCodeImpl(method, ownerClassName) else (false, Set.empty[LabelNode]) traceIfChanged("dce") // BOX-UNBOX - val runBoxUnbox = compilerSettings.YoptBoxUnbox && (requestBoxUnbox || nullnessOptChanged) + val runBoxUnbox = compilerSettings.optBoxUnbox && (requestBoxUnbox || nullnessOptChanged) val boxUnboxChanged = runBoxUnbox && boxUnboxElimination(method, ownerClassName) traceIfChanged("boxUnbox") // COPY PROPAGATION - val runCopyProp = compilerSettings.YoptCopyPropagation && (firstIteration || boxUnboxChanged) + val runCopyProp = compilerSettings.optCopyPropagation && (firstIteration || boxUnboxChanged) val copyPropChanged = runCopyProp && copyPropagation(method, ownerClassName) traceIfChanged("copyProp") // STALE STORES - val runStaleStores = compilerSettings.YoptCopyPropagation && (requestStaleStores || nullnessOptChanged || codeRemoved || boxUnboxChanged || copyPropChanged) + val runStaleStores = compilerSettings.optCopyPropagation && (requestStaleStores || nullnessOptChanged || codeRemoved || boxUnboxChanged || copyPropChanged) val storesRemoved = runStaleStores && eliminateStaleStores(method, ownerClassName) traceIfChanged("staleStores") // REDUNDANT CASTS - val runRedundantCasts = compilerSettings.YoptRedundantCasts && (firstIteration || boxUnboxChanged) + val runRedundantCasts = compilerSettings.optRedundantCasts && (firstIteration || boxUnboxChanged) val castRemoved = runRedundantCasts && eliminateRedundantCasts(method, ownerClassName) traceIfChanged("redundantCasts") // PUSH-POP - val runPushPop = compilerSettings.YoptCopyPropagation && (requestPushPop || firstIteration || storesRemoved || castRemoved) + val runPushPop = compilerSettings.optCopyPropagation && (requestPushPop || firstIteration || storesRemoved || castRemoved) val pushPopRemoved = runPushPop && eliminatePushPop(method, ownerClassName) traceIfChanged("pushPop") // STORE-LOAD PAIRS - val runStoreLoad = compilerSettings.YoptCopyPropagation && (requestStoreLoad || boxUnboxChanged || copyPropChanged || pushPopRemoved) + val runStoreLoad = compilerSettings.optCopyPropagation && (requestStoreLoad || boxUnboxChanged || copyPropChanged || pushPopRemoved) val storeLoadRemoved = runStoreLoad && eliminateStoreLoad(method) traceIfChanged("storeLoadPairs") @@ -312,7 +312,7 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { // SIMPLIFY JUMPS // almost all of the above optimizations enable simplifying more jumps, so we just run it in every iteration - val runSimplifyJumps = compilerSettings.YoptSimplifyJumps + val runSimplifyJumps = compilerSettings.optSimplifyJumps val jumpsChanged = runSimplifyJumps && simplifyJumps(method) traceIfChanged("simplifyJumps") @@ -358,21 +358,21 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { requestPushPop = true, requestStoreLoad = true, firstIteration = true) - if (compilerSettings.YoptUnreachableCode) unreachableCodeEliminated += method + if (compilerSettings.optUnreachableCode) unreachableCodeEliminated += method r } else (false, false) // (*) Removing stale local variable descriptors is required for correctness, see comment in `methodOptimizations` val localsRemoved = - if (compilerSettings.YoptCompactLocals) compactLocalVariables(method) // also removes unused + if (compilerSettings.optCompactLocals) compactLocalVariables(method) // also removes unused else if (requireEliminateUnusedLocals) removeUnusedLocalVariableNodes(method)() // (*) else false traceIfChanged("localVariables") - val lineNumbersRemoved = if (compilerSettings.YoptUnreachableCode) removeEmptyLineNumbers(method) else false + val lineNumbersRemoved = if (compilerSettings.optUnreachableCode) removeEmptyLineNumbers(method) else false traceIfChanged("lineNumbers") - val labelsRemoved = if (compilerSettings.YoptUnreachableCode) removeEmptyLabelNodes(method) else false + val labelsRemoved = if (compilerSettings.optUnreachableCode) removeEmptyLabelNodes(method) else false traceIfChanged("labels") // assert that local variable annotations are empty (we don't emit them) - otherwise we'd have diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 9a0d86a94df1..21a6850a43de 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -205,7 +205,7 @@ trait ScalaSettings extends AbsScalaSettings val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly() val Ydelambdafy = ChoiceSetting ("-Ydelambdafy", "strategy", "Strategy used for translating lambdas into JVM code.", List("inline", "method"), "method") - object YoptChoices extends MultiChoiceEnumeration { + object optChoices extends MultiChoiceEnumeration { val unreachableCode = Choice("unreachable-code", "Eliminate unreachable code, exception handlers guarding no instructions, redundant metadata (debug information, line numbers).") val simplifyJumps = Choice("simplify-jumps", "Simplify branching instructions, eliminate unnecessary ones.") val compactLocals = Choice("compact-locals", "Eliminate empty slots in the sequence of local variables.") @@ -217,8 +217,8 @@ trait ScalaSettings extends AbsScalaSettings val inlineProject = Choice("inline-project", "Inline only methods defined in the files being compiled. Enables unreachable-code.") val inlineGlobal = Choice("inline-global", "Inline methods from any source, including classfiles on the compile classpath. Enables unreachable-code.") - // note: unlike the other optimizer levels, "l:none" appears up in the `Yopt.value` set because it's not an expanding option (expandsTo is empty) - val lNone = Choice("l:none", "Disable optimizations. Takes precedence: `-Yopt:l:none,+box-unbox` / `-Yopt:l:none -Yopt:box-unbox` don't enable box-unbox.") + // note: unlike the other optimizer levels, "l:none" appears up in the `opt.value` set because it's not an expanding option (expandsTo is empty) + val lNone = Choice("l:none", "Disable optimizations. Takes precedence: `-opt:l:none,+box-unbox` / `-opt:l:none -opt:box-unbox` don't enable box-unbox.") private val defaultChoices = List(unreachableCode) val lDefault = Choice("l:default", "Enable default optimizations: "+ defaultChoices.mkString("", ",", "."), expandsTo = defaultChoices) @@ -234,37 +234,37 @@ trait ScalaSettings extends AbsScalaSettings } // We don't use the `default` parameter of `MultiChoiceSetting`: it specifies the default values - // when `-Yopt` is passed without explicit choices. When `-Yopt` is not explicitly specified, the - // set `Yopt.value` is empty. - val Yopt = MultiChoiceSetting( - name = "-Yopt", + // when `-opt` is passed without explicit choices. When `-opt` is not explicitly specified, the + // set `opt.value` is empty. + val opt = MultiChoiceSetting( + name = "-opt", helpArg = "optimization", descr = "Enable optimizations", - domain = YoptChoices) + domain = optChoices) - private def optEnabled(choice: YoptChoices.Choice) = { - !Yopt.contains(YoptChoices.lNone) && { - Yopt.contains(choice) || - !Yopt.isSetByUser && YoptChoices.lDefault.expandsTo.contains(choice) + private def optEnabled(choice: optChoices.Choice) = { + !opt.contains(optChoices.lNone) && { + opt.contains(choice) || + !opt.isSetByUser && optChoices.lDefault.expandsTo.contains(choice) } } - def YoptNone = Yopt.contains(YoptChoices.lNone) - def YoptUnreachableCode = optEnabled(YoptChoices.unreachableCode) - def YoptSimplifyJumps = optEnabled(YoptChoices.simplifyJumps) - def YoptCompactLocals = optEnabled(YoptChoices.compactLocals) - def YoptCopyPropagation = optEnabled(YoptChoices.copyPropagation) - def YoptRedundantCasts = optEnabled(YoptChoices.redundantCasts) - def YoptBoxUnbox = optEnabled(YoptChoices.boxUnbox) - def YoptNullnessTracking = optEnabled(YoptChoices.nullnessTracking) - def YoptClosureInvocations = optEnabled(YoptChoices.closureInvocations) + def optNone = opt.contains(optChoices.lNone) + def optUnreachableCode = optEnabled(optChoices.unreachableCode) + def optSimplifyJumps = optEnabled(optChoices.simplifyJumps) + def optCompactLocals = optEnabled(optChoices.compactLocals) + def optCopyPropagation = optEnabled(optChoices.copyPropagation) + def optRedundantCasts = optEnabled(optChoices.redundantCasts) + def optBoxUnbox = optEnabled(optChoices.boxUnbox) + def optNullnessTracking = optEnabled(optChoices.nullnessTracking) + def optClosureInvocations = optEnabled(optChoices.closureInvocations) - def YoptInlineProject = optEnabled(YoptChoices.inlineProject) - def YoptInlineGlobal = optEnabled(YoptChoices.inlineGlobal) - def YoptInlinerEnabled = YoptInlineProject || YoptInlineGlobal + def optInlineProject = optEnabled(optChoices.inlineProject) + def optInlineGlobal = optEnabled(optChoices.inlineGlobal) + def optInlinerEnabled = optInlineProject || optInlineGlobal - def YoptBuildCallGraph = YoptInlinerEnabled || YoptClosureInvocations - def YoptAddToBytecodeRepository = YoptBuildCallGraph || YoptInlinerEnabled || YoptClosureInvocations + def optBuildCallGraph = optInlinerEnabled || optClosureInvocations + def optAddToBytecodeRepository = optBuildCallGraph || optInlinerEnabled || optClosureInvocations val YoptInlineHeuristics = ChoiceSetting( name = "-Yopt-inline-heuristics", @@ -273,7 +273,7 @@ trait ScalaSettings extends AbsScalaSettings choices = List("at-inline-annotated", "everything", "default"), default = "default") - object YoptWarningsChoices extends MultiChoiceEnumeration { + object optWarningsChoices extends MultiChoiceEnumeration { val none = Choice("none" , "No optimizer warnings.") val atInlineFailedSummary = Choice("at-inline-failed-summary" , "One-line summary if there were @inline method calls that could not be inlined.") val atInlineFailed = Choice("at-inline-failed" , "A detailed warning for each @inline method call that could not be inlined.") @@ -283,24 +283,24 @@ trait ScalaSettings extends AbsScalaSettings val noInlineMissingScalaInlineInfoAttr = Choice("no-inline-missing-attribute", "Warn if an inlining decision cannot be made because a Scala classfile does not have a ScalaInlineInfo attribute.") } - val YoptWarnings = MultiChoiceSetting( - name = "-Yopt-warnings", + val optWarnings = MultiChoiceSetting( + name = "-opt-warnings", helpArg = "warning", descr = "Enable optimizer warnings", - domain = YoptWarningsChoices, - default = Some(List(YoptWarningsChoices.atInlineFailed.name))) + domain = optWarningsChoices, + default = Some(List(optWarningsChoices.atInlineFailed.name))) - def YoptWarningsSummaryOnly = YoptWarnings.value subsetOf Set(YoptWarningsChoices.none, YoptWarningsChoices.atInlineFailedSummary) + def optWarningsSummaryOnly = optWarnings.value subsetOf Set(optWarningsChoices.none, optWarningsChoices.atInlineFailedSummary) - def YoptWarningEmitAtInlineFailed = - !YoptWarnings.isSetByUser || - YoptWarnings.contains(YoptWarningsChoices.atInlineFailedSummary) || - YoptWarnings.contains(YoptWarningsChoices.atInlineFailed) || - YoptWarnings.contains(YoptWarningsChoices.anyInlineFailed) + def optWarningEmitAtInlineFailed = + !optWarnings.isSetByUser || + optWarnings.contains(optWarningsChoices.atInlineFailedSummary) || + optWarnings.contains(optWarningsChoices.atInlineFailed) || + optWarnings.contains(optWarningsChoices.anyInlineFailed) - def YoptWarningNoInlineMixed = YoptWarnings.contains(YoptWarningsChoices.noInlineMixed) - def YoptWarningNoInlineMissingBytecode = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingBytecode) - def YoptWarningNoInlineMissingScalaInlineInfoAttr = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingScalaInlineInfoAttr) + def optWarningNoInlineMixed = optWarnings.contains(optWarningsChoices.noInlineMixed) + def optWarningNoInlineMissingBytecode = optWarnings.contains(optWarningsChoices.noInlineMissingBytecode) + def optWarningNoInlineMissingScalaInlineInfoAttr = optWarnings.contains(optWarningsChoices.noInlineMissingScalaInlineInfoAttr) val YoptTrace = StringSetting("-Yopt-trace", "package/Class.method", "Trace the optimizer progress for a specific method.", "") @@ -340,8 +340,8 @@ trait ScalaSettings extends AbsScalaSettings val future = BooleanSetting("-Xfuture", "Turn on future language features.") enablingIfNotSetByUser futureSettings val optimise = BooleanSetting("-optimise", "Compiler flag for the optimizer in Scala 2.11") .withAbbreviation("-optimize") - .withDeprecationMessage("In 2.12, -optimise enables -Yopt:l:classpath. Check -Yopt:help for using the Scala 2.12 optimizer.") - .withPostSetHook(_ => Yopt.tryToSet(List(YoptChoices.lClasspath.name))) + .withDeprecationMessage("In 2.12, -optimise enables -opt:l:classpath. Check -opt:help for using the Scala 2.12 optimizer.") + .withPostSetHook(_ => opt.tryToSet(List(optChoices.lClasspath.name))) val Xexperimental = BooleanSetting("-Xexperimental", "Enable experimental extensions.") enablingIfNotSetByUser experimentalSettings // Feature extensions diff --git a/test/files/instrumented/inline-in-constructors.flags b/test/files/instrumented/inline-in-constructors.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/instrumented/inline-in-constructors.flags +++ b/test/files/instrumented/inline-in-constructors.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/jvm/bytecode-test-example.flags b/test/files/jvm/bytecode-test-example.flags index bc22511cffca..213d7425d189 100644 --- a/test/files/jvm/bytecode-test-example.flags +++ b/test/files/jvm/bytecode-test-example.flags @@ -1 +1 @@ --Yopt:l:none +-opt:l:none diff --git a/test/files/jvm/unreachable/Foo_1.flags b/test/files/jvm/unreachable/Foo_1.flags index ac9438e8d0ca..d0a417b3c888 100644 --- a/test/files/jvm/unreachable/Foo_1.flags +++ b/test/files/jvm/unreachable/Foo_1.flags @@ -1 +1 @@ --Yopt:l:default \ No newline at end of file +-opt:l:default \ No newline at end of file diff --git a/test/files/neg/inlineIndyLambdaPrivate.flags b/test/files/neg/inlineIndyLambdaPrivate.flags index 01b466bd8c56..b38f5b8411ac 100644 --- a/test/files/neg/inlineIndyLambdaPrivate.flags +++ b/test/files/neg/inlineIndyLambdaPrivate.flags @@ -1 +1 @@ --Yopt:l:classpath -Yopt-inline-heuristics:everything -Yopt-warnings:_ -Xfatal-warnings \ No newline at end of file +-opt:l:classpath -Yopt-inline-heuristics:everything -opt-warnings:_ -Xfatal-warnings \ No newline at end of file diff --git a/test/files/neg/inlineMaxSize.flags b/test/files/neg/inlineMaxSize.flags index 18b474e7970e..e765b66af2db 100644 --- a/test/files/neg/inlineMaxSize.flags +++ b/test/files/neg/inlineMaxSize.flags @@ -1 +1 @@ --Ydelambdafy:method -Yopt:l:classpath -Yopt-warnings -Xfatal-warnings \ No newline at end of file +-Ydelambdafy:method -opt:l:classpath -opt-warnings -Xfatal-warnings \ No newline at end of file diff --git a/test/files/neg/optimiseDeprecated.check b/test/files/neg/optimiseDeprecated.check index d51d48f02334..16ab3bbf1a91 100644 --- a/test/files/neg/optimiseDeprecated.check +++ b/test/files/neg/optimiseDeprecated.check @@ -1,4 +1,4 @@ -warning: -optimise is deprecated: In 2.12, -optimise enables -Yopt:l:classpath. Check -Yopt:help for using the Scala 2.12 optimizer. +warning: -optimise is deprecated: In 2.12, -optimise enables -opt:l:classpath. Check -opt:help for using the Scala 2.12 optimizer. error: No warnings can be incurred under -Xfatal-warnings. one warning found one error found diff --git a/test/files/neg/partestInvalidFlag.check b/test/files/neg/partestInvalidFlag.check index 812191dc2254..7a54e3aa43ad 100644 --- a/test/files/neg/partestInvalidFlag.check +++ b/test/files/neg/partestInvalidFlag.check @@ -1,4 +1,4 @@ error: bad option: '-badCompilerFlag' -error: bad options: -badCompilerFlag notAFlag -Yopt:badChoice -error: flags file may only contain compiler options, found: -badCompilerFlag notAFlag -Yopt:badChoice +error: bad options: -badCompilerFlag notAFlag -opt:badChoice +error: flags file may only contain compiler options, found: -badCompilerFlag notAFlag -opt:badChoice three errors found diff --git a/test/files/neg/partestInvalidFlag.flags b/test/files/neg/partestInvalidFlag.flags index 68884532b9f8..d45fd3180904 100644 --- a/test/files/neg/partestInvalidFlag.flags +++ b/test/files/neg/partestInvalidFlag.flags @@ -1 +1 @@ --badCompilerFlag notAFlag -Yopt:badChoice +-badCompilerFlag notAFlag -opt:badChoice diff --git a/test/files/neg/sealed-final-neg.flags b/test/files/neg/sealed-final-neg.flags index 673aca893135..f2f36c1771c5 100644 --- a/test/files/neg/sealed-final-neg.flags +++ b/test/files/neg/sealed-final-neg.flags @@ -1 +1 @@ --Xfatal-warnings -Yopt:l:project -Yopt-warnings \ No newline at end of file +-Xfatal-warnings -opt:l:project -opt-warnings \ No newline at end of file diff --git a/test/files/pos/inline-access-levels.flags b/test/files/pos/inline-access-levels.flags index 9af9168a20e7..faa7d2b186f5 100644 --- a/test/files/pos/inline-access-levels.flags +++ b/test/files/pos/inline-access-levels.flags @@ -1 +1 @@ --Yopt:l:classpath -Xfatal-warnings -Yopt-warnings +-opt:l:classpath -Xfatal-warnings -opt-warnings diff --git a/test/files/pos/t3234.flags b/test/files/pos/t3234.flags index 13878e00a93e..b88ec8709d6e 100644 --- a/test/files/pos/t3234.flags +++ b/test/files/pos/t3234.flags @@ -1 +1 @@ --Yopt:l:project -Yopt-warnings -Xfatal-warnings +-opt:l:project -opt-warnings -Xfatal-warnings diff --git a/test/files/pos/t3420.flags b/test/files/pos/t3420.flags index 397969bb1d57..5eea92d94acb 100644 --- a/test/files/pos/t3420.flags +++ b/test/files/pos/t3420.flags @@ -1 +1 @@ --Yopt-warnings -Yopt:l:classpath -Xfatal-warnings \ No newline at end of file +-opt-warnings -opt:l:classpath -Xfatal-warnings \ No newline at end of file diff --git a/test/files/pos/t4840.flags b/test/files/pos/t4840.flags index 422d6be43108..768ca4f13b95 100644 --- a/test/files/pos/t4840.flags +++ b/test/files/pos/t4840.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-opt:l:classpath \ No newline at end of file diff --git a/test/files/pos/t8410.flags b/test/files/pos/t8410.flags index c3065096cfbd..85e425754141 100644 --- a/test/files/pos/t8410.flags +++ b/test/files/pos/t8410.flags @@ -1 +1 @@ --Yopt:l:project -Xfatal-warnings -deprecation:false -Yopt-warnings:none +-opt:l:project -Xfatal-warnings -deprecation:false -opt-warnings:none diff --git a/test/files/pos/t9111-inliner-workaround.flags b/test/files/pos/t9111-inliner-workaround.flags index 422d6be43108..768ca4f13b95 100644 --- a/test/files/pos/t9111-inliner-workaround.flags +++ b/test/files/pos/t9111-inliner-workaround.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-opt:l:classpath \ No newline at end of file diff --git a/test/files/run/bcodeInlinerMixed.flags b/test/files/run/bcodeInlinerMixed.flags index 422d6be43108..768ca4f13b95 100644 --- a/test/files/run/bcodeInlinerMixed.flags +++ b/test/files/run/bcodeInlinerMixed.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-opt:l:classpath \ No newline at end of file diff --git a/test/files/run/classfile-format-51.scala b/test/files/run/classfile-format-51.scala index 3ef0640b840e..3a6c4861f193 100644 --- a/test/files/run/classfile-format-51.scala +++ b/test/files/run/classfile-format-51.scala @@ -16,7 +16,7 @@ import Opcodes._ // verify. So the test includes a version check that short-circuits the whole test // on JDK 6 object Test extends DirectTest { - override def extraSettings: String = "-Yopt:l:classpath -usejavacp -d " + testOutput.path + " -cp " + testOutput.path + override def extraSettings: String = "-opt:l:classpath -usejavacp -d " + testOutput.path + " -cp " + testOutput.path def generateClass() { val invokerClassName = "DynamicInvoker" diff --git a/test/files/run/classfile-format-52.scala b/test/files/run/classfile-format-52.scala index ebd0826303a4..03ceeb074fc6 100644 --- a/test/files/run/classfile-format-52.scala +++ b/test/files/run/classfile-format-52.scala @@ -13,7 +13,7 @@ import Opcodes._ // By its nature the test can only work on JDK 8+ because under JDK 7- the // interface won't verify. object Test extends DirectTest { - override def extraSettings: String = "-Yopt:l:classpath -usejavacp -d " + testOutput.path + " -cp " + testOutput.path + override def extraSettings: String = "-opt:l:classpath -usejavacp -d " + testOutput.path + " -cp " + testOutput.path def generateInterface() { val interfaceName = "HasDefaultMethod" diff --git a/test/files/run/finalvar.flags b/test/files/run/finalvar.flags index a8c7600a0322..c74d0cd32789 100644 --- a/test/files/run/finalvar.flags +++ b/test/files/run/finalvar.flags @@ -1 +1 @@ --Yoverride-vars -Yopt:l:project \ No newline at end of file +-Yoverride-vars -opt:l:project \ No newline at end of file diff --git a/test/files/run/icode-reader-dead-code.scala b/test/files/run/icode-reader-dead-code.scala index df31219dd500..f646455c8950 100644 --- a/test/files/run/icode-reader-dead-code.scala +++ b/test/files/run/icode-reader-dead-code.scala @@ -36,7 +36,7 @@ object Test extends DirectTest { // If inlining fails, the compiler will issue an inliner warning that is not present in the // check file - compileString(newCompiler("-usejavacp", "-Yopt:l:classpath"))(bCode) + compileString(newCompiler("-usejavacp", "-opt:l:classpath"))(bCode) } def readClass(file: String) = { diff --git a/test/files/run/noInlineUnknownIndy/Test.scala b/test/files/run/noInlineUnknownIndy/Test.scala index 8d2d20a3cd52..c6d227b6f2c2 100644 --- a/test/files/run/noInlineUnknownIndy/Test.scala +++ b/test/files/run/noInlineUnknownIndy/Test.scala @@ -11,7 +11,7 @@ object Test extends DirectTest { def compileCode(code: String) = { val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") - compileString(newCompiler("-cp", classpath, "-d", testOutput.path, "-Yopt:l:classpath", "-Yopt-inline-heuristics:everything", "-Yopt-warnings:_"))(code) + compileString(newCompiler("-cp", classpath, "-d", testOutput.path, "-opt:l:classpath", "-Yopt-inline-heuristics:everything", "-opt-warnings:_"))(code) } def show(): Unit = { diff --git a/test/files/run/nothingTypeDce.flags b/test/files/run/nothingTypeDce.flags index 8785c036f63d..475f6db67c5f 100644 --- a/test/files/run/nothingTypeDce.flags +++ b/test/files/run/nothingTypeDce.flags @@ -1 +1 @@ --Yopt:unreachable-code +-opt:unreachable-code diff --git a/test/files/run/nothingTypeDce.scala b/test/files/run/nothingTypeDce.scala index 5c3a0731fd47..cb1e59e45c27 100644 --- a/test/files/run/nothingTypeDce.scala +++ b/test/files/run/nothingTypeDce.scala @@ -1,6 +1,6 @@ // See comment in BCodeBodyBuilder -// -Yopt:unreachable-code +// -opt:unreachable-code class C { // can't just emit a call to ???, that returns value of type Nothing$ (not Int). diff --git a/test/files/run/nothingTypeNoOpt.flags b/test/files/run/nothingTypeNoOpt.flags index bc22511cffca..213d7425d189 100644 --- a/test/files/run/nothingTypeNoOpt.flags +++ b/test/files/run/nothingTypeNoOpt.flags @@ -1 +1 @@ --Yopt:l:none +-opt:l:none diff --git a/test/files/run/nothingTypeNoOpt.scala b/test/files/run/nothingTypeNoOpt.scala index 33b20ba851a4..cc68364bf988 100644 --- a/test/files/run/nothingTypeNoOpt.scala +++ b/test/files/run/nothingTypeNoOpt.scala @@ -1,6 +1,6 @@ // See comment in BCodeBodyBuilder -// -target:jvm-1.6 -Yopt:l:none +// -target:jvm-1.6 -opt:l:none // target enables stack map frame generation class C { diff --git a/test/files/run/synchronized.flags b/test/files/run/synchronized.flags index 19c578e4ad0b..82eb1b9bdd6f 100644 --- a/test/files/run/synchronized.flags +++ b/test/files/run/synchronized.flags @@ -1 +1 @@ --Yopt:l:project +-opt:l:project diff --git a/test/files/run/t2106.flags b/test/files/run/t2106.flags index b0139685fa17..cde9a0c4e625 100644 --- a/test/files/run/t2106.flags +++ b/test/files/run/t2106.flags @@ -1 +1 @@ --Yopt-warnings -Yopt:l:classpath +-opt-warnings -opt:l:classpath diff --git a/test/files/run/t3509.flags b/test/files/run/t3509.flags index 422d6be43108..768ca4f13b95 100644 --- a/test/files/run/t3509.flags +++ b/test/files/run/t3509.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-opt:l:classpath \ No newline at end of file diff --git a/test/files/run/t3569.flags b/test/files/run/t3569.flags index 422d6be43108..768ca4f13b95 100644 --- a/test/files/run/t3569.flags +++ b/test/files/run/t3569.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-opt:l:classpath \ No newline at end of file diff --git a/test/files/run/t4285.flags b/test/files/run/t4285.flags index 422d6be43108..768ca4f13b95 100644 --- a/test/files/run/t4285.flags +++ b/test/files/run/t4285.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-opt:l:classpath \ No newline at end of file diff --git a/test/files/run/t4935.flags b/test/files/run/t4935.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t4935.flags +++ b/test/files/run/t4935.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/run/t5789.scala b/test/files/run/t5789.scala index 677c9ca229b7..893294b56b1b 100644 --- a/test/files/run/t5789.scala +++ b/test/files/run/t5789.scala @@ -5,7 +5,7 @@ import scala.tools.partest.ReplTest object Test extends ReplTest { - override def extraSettings = "-Yopt:l:classpath" + override def extraSettings = "-opt:l:classpath" def code = """ val n = 2 () => n diff --git a/test/files/run/t6102.flags b/test/files/run/t6102.flags index db58cf3b4c45..7f938c550fea 100644 --- a/test/files/run/t6102.flags +++ b/test/files/run/t6102.flags @@ -1 +1 @@ --Yopt:l:classpath -Xfatal-warnings +-opt:l:classpath -Xfatal-warnings diff --git a/test/files/run/t6188.flags b/test/files/run/t6188.flags index 422d6be43108..768ca4f13b95 100644 --- a/test/files/run/t6188.flags +++ b/test/files/run/t6188.flags @@ -1 +1 @@ --Yopt:l:classpath \ No newline at end of file +-opt:l:classpath \ No newline at end of file diff --git a/test/files/run/t7407.flags b/test/files/run/t7407.flags index bc22511cffca..213d7425d189 100644 --- a/test/files/run/t7407.flags +++ b/test/files/run/t7407.flags @@ -1 +1 @@ --Yopt:l:none +-opt:l:none diff --git a/test/files/run/t7459b-optimize.flags b/test/files/run/t7459b-optimize.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t7459b-optimize.flags +++ b/test/files/run/t7459b-optimize.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/run/t7582.flags b/test/files/run/t7582.flags index 1f45833effde..7e64669429c1 100644 --- a/test/files/run/t7582.flags +++ b/test/files/run/t7582.flags @@ -1 +1 @@ --Yopt:l:classpath -Yopt-warnings \ No newline at end of file +-opt:l:classpath -opt-warnings \ No newline at end of file diff --git a/test/files/run/t7582b.flags b/test/files/run/t7582b.flags index 1f45833effde..7e64669429c1 100644 --- a/test/files/run/t7582b.flags +++ b/test/files/run/t7582b.flags @@ -1 +1 @@ --Yopt:l:classpath -Yopt-warnings \ No newline at end of file +-opt:l:classpath -opt-warnings \ No newline at end of file diff --git a/test/files/run/t7852.flags b/test/files/run/t7852.flags index bc22511cffca..213d7425d189 100644 --- a/test/files/run/t7852.flags +++ b/test/files/run/t7852.flags @@ -1 +1 @@ --Yopt:l:none +-opt:l:none diff --git a/test/files/run/t8601-closure-elim.flags b/test/files/run/t8601-closure-elim.flags index 642187ff4c17..24396d4d02bf 100644 --- a/test/files/run/t8601-closure-elim.flags +++ b/test/files/run/t8601-closure-elim.flags @@ -1 +1 @@ --Ydelambdafy:method -Yopt:l:classpath +-Ydelambdafy:method -opt:l:classpath diff --git a/test/files/run/t8601.flags b/test/files/run/t8601.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t8601.flags +++ b/test/files/run/t8601.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/run/t8601b.flags b/test/files/run/t8601b.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t8601b.flags +++ b/test/files/run/t8601b.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/run/t8601c.flags b/test/files/run/t8601c.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t8601c.flags +++ b/test/files/run/t8601c.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/run/t8601d.flags b/test/files/run/t8601d.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t8601d.flags +++ b/test/files/run/t8601d.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/run/t8601e.flags b/test/files/run/t8601e.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t8601e.flags +++ b/test/files/run/t8601e.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/run/t8925.flags b/test/files/run/t8925.flags index bc22511cffca..213d7425d189 100644 --- a/test/files/run/t8925.flags +++ b/test/files/run/t8925.flags @@ -1 +1 @@ --Yopt:l:none +-opt:l:none diff --git a/test/files/run/t9003.flags b/test/files/run/t9003.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t9003.flags +++ b/test/files/run/t9003.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/files/run/t9403.flags b/test/files/run/t9403.flags index 65caa3736e84..63535a7f4fcc 100644 --- a/test/files/run/t9403.flags +++ b/test/files/run/t9403.flags @@ -1 +1 @@ --Yopt:l:classpath +-opt:l:classpath diff --git a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala index 0144fa7366a3..58df4691e473 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala @@ -11,7 +11,7 @@ import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) class BTypesTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:none" + override def compilerArgs = "-opt:l:none" import compiler.global locally { new global.Run() // initializes some of the compiler diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala index 7fdfb315779d..f835e9b14010 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala @@ -12,7 +12,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class DirectCompileTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:method" + override def compilerArgs = "-opt:l:method" import compiler._ @Test diff --git a/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala index 003162c1ad41..8cf6a655d232 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala @@ -11,7 +11,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class OptimizedBytecodeTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:classpath -Yopt-warnings" + override def compilerArgs = "-opt:l:classpath -opt-warnings" import compiler._ @Test diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala index b0a86dfd28b3..1de5aa28ca3d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala @@ -17,7 +17,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class NullnessAnalyzerTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:none" + override def compilerArgs = "-opt:l:none" import compiler._ import global.genBCode.bTypes.backendUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala index fc2678523764..8cb04822de68 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala @@ -16,7 +16,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class ProdConsAnalyzerTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:none" + override def compilerArgs = "-opt:l:none" import compiler._ import global.genBCode.bTypes.backendUtils._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala index 025248ac2880..33ca6a5fd25a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/AnalyzerTest.scala @@ -15,7 +15,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class AnalyzerTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:none" + override def compilerArgs = "-opt:l:none" import compiler._ @Test diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala index e7aea71e7215..c23c60f7ad05 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala @@ -14,7 +14,7 @@ import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) class BTypesFromClassfileTest extends BytecodeTesting { // inliner enabled -> inlineInfos are collected (and compared) in ClassBTypes - override def compilerArgs = "-Yopt:inline-global" + override def compilerArgs = "-opt:inline-global" import compiler.global._ import definitions._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala index 630416a92582..80fbba133e7e 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala @@ -18,7 +18,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class CallGraphTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:inline-global -Yopt-warnings" + override def compilerArgs = "-opt:inline-global -opt-warnings" import compiler._ import global.genBCode.bTypes val notPerRun: List[Clearable] = List( diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala index 218b02f82259..2da2ecdb723a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala @@ -13,7 +13,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class ClosureOptimizerTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:classpath -Yopt-warnings:_" + override def compilerArgs = "-opt:l:classpath -opt-warnings:_" import compiler._ @Test diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala index c3748a05bd46..6f54f170b59a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala @@ -15,8 +15,8 @@ import scala.tools.testing.ClearAfterClass class CompactLocalVariablesTest extends ClearAfterClass { // recurse-unreachable-jumps is required for eliminating catch blocks, in the first dce round they // are still live.only after eliminating the empty handler the catch blocks become unreachable. - val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code,compact-locals")) - val noCompactVarsCompiler = cached("noCompactVarsCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) + val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-opt:unreachable-code,compact-locals")) + val noCompactVarsCompiler = cached("noCompactVarsCompiler", () => newCompiler(extraArgs = "-opt:unreachable-code")) @Test def compactUnused(): Unit = { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala index 3324058cb762..77215304fdd6 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala @@ -15,10 +15,10 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class EmptyExceptionHandlersTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:unreachable-code" + override def compilerArgs = "-opt:unreachable-code" def dceCompiler = compiler - val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) + val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-opt:l:none")) val exceptionDescriptor = "java/lang/Exception" diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala index e45d7139a3be..a691d634718f 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala @@ -16,7 +16,7 @@ class InlineInfoTest extends BytecodeTesting { import compiler.global import global.genBCode.bTypes - override def compilerArgs = "-Yopt:l:classpath" + override def compilerArgs = "-opt:l:classpath" def notPerRun: List[Clearable] = List( bTypes.classBTypeFromInternalName, diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index f0913f36318d..6161dc7b7324 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -11,12 +11,12 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class InlineWarningTest extends BytecodeTesting { - def optCp = "-Yopt:l:classpath" - override def compilerArgs = s"$optCp -Yopt-warnings" + def optCp = "-opt:l:classpath" + override def compilerArgs = s"$optCp -opt-warnings" import compiler._ - val compilerWarnAll = cached("compilerWarnAll", () => newCompiler(extraArgs = s"$optCp -Yopt-warnings:_")) + val compilerWarnAll = cached("compilerWarnAll", () => newCompiler(extraArgs = s"$optCp -opt-warnings:_")) @Test def nonFinal(): Unit = { @@ -87,10 +87,10 @@ class InlineWarningTest extends BytecodeTesting { assert(c == 1, c) // no warnings here - newCompiler(extraArgs = s"$optCp -Yopt-warnings:none").compileToBytes(scalaCode, List((javaCode, "A.java"))) + newCompiler(extraArgs = s"$optCp -opt-warnings:none").compileToBytes(scalaCode, List((javaCode, "A.java"))) c = 0 - newCompiler(extraArgs = s"$optCp -Yopt-warnings:no-inline-mixed").compileToBytes(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) + newCompiler(extraArgs = s"$optCp -opt-warnings:no-inline-mixed").compileToBytes(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)}) assert(c == 2, c) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala index c2ada8afec1f..3cb1fbdae6ff 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala @@ -14,7 +14,7 @@ import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) class InlinerIllegalAccessTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:none" + override def compilerArgs = "-opt:l:none" import compiler._ import global.genBCode.bTypes._ diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala index b196f1a9ba4d..a2513cacdc47 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala @@ -10,7 +10,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class InlinerSeparateCompilationTest { - val args = "-Yopt:l:classpath" + val args = "-opt:l:classpath" @Test def inlnieMixedinMember(): Unit = { @@ -32,7 +32,7 @@ class InlinerSeparateCompilationTest { """.stripMargin val warn = "T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" - val List(c, o, oMod, t) = compileClassesSeparately(List(codeA, codeB), args + " -Yopt-warnings", _.msg contains warn) + val List(c, o, oMod, t) = compileClassesSeparately(List(codeA, codeB), args + " -opt-warnings", _.msg contains warn) assertInvoke(getMethod(c, "t1"), "T", "f") assertNoInvoke(getMethod(c, "t2")) assertNoInvoke(getMethod(c, "t3")) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index fd020c7d9390..f1e3e9b9e145 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -19,9 +19,9 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class InlinerTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:classpath -Yopt-warnings" + override def compilerArgs = "-opt:l:classpath -opt-warnings" - val inlineOnlyCompiler = cached("inlineOnlyCompiler", () => newCompiler(extraArgs = "-Yopt:inline-project")) + val inlineOnlyCompiler = cached("inlineOnlyCompiler", () => newCompiler(extraArgs = "-opt:inline-project")) import compiler._ import global.genBCode.bTypes @@ -825,7 +825,7 @@ class InlinerTest extends BytecodeTesting { var c = 0 - newCompiler(extraArgs = compilerArgs + " -Yopt-warnings:_").compileClasses( + newCompiler(extraArgs = compilerArgs + " -opt-warnings:_").compileClasses( scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; i.msg contains warn}) @@ -1459,7 +1459,7 @@ class InlinerTest extends BytecodeTesting { val codeA = "final class A { @inline def f = 1 }" val codeB = "class B { def t(a: A) = a.f }" // tests that no warning is emitted - val List(a, b) = compileClassesSeparately(List(codeA, codeB), extraArgs = "-Yopt:l:project -Yopt-warnings") + val List(a, b) = compileClassesSeparately(List(codeA, codeB), extraArgs = "-opt:l:project -opt-warnings") assertInvoke(getMethod(b, "t"), "A", "f") } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index fa76c0d93086..9675e2e4456f 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -17,7 +17,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class MethodLevelOptsTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:method" + override def compilerArgs = "-opt:l:method" import compiler._ def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1)) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala index 5bd285f97f7d..4791a29bfbb7 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala @@ -14,7 +14,7 @@ import scala.tools.testing.BytecodeTesting @RunWith(classOf[JUnit4]) class ScalaInlineInfoTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:l:none" + override def compilerArgs = "-opt:l:none" import compiler._ def inlineInfo(c: ClassNode): InlineInfo = c.attrs.asScala.collect({ case a: InlineInfoAttribute => a.inlineInfo }).head diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala index 63bbcc396bb6..68ce61b48aa5 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala @@ -17,9 +17,9 @@ import scala.tools.testing.ClearAfterClass class UnreachableCodeTest extends ClearAfterClass { // jvm-1.6 enables emitting stack map frames, which impacts the code generation wrt dead basic blocks, // see comment in BCodeBodyBuilder - val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:method")) - val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-Yopt:unreachable-code")) - val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-Yopt:l:none")) + val methodOptCompiler = cached("methodOptCompiler", () => newCompiler(extraArgs = "-opt:l:method")) + val dceCompiler = cached("dceCompiler", () => newCompiler(extraArgs = "-opt:unreachable-code")) + val noOptCompiler = cached("noOptCompiler", () => newCompiler(extraArgs = "-opt:l:none")) def assertEliminateDead(code: (Instruction, Boolean)*): Unit = { val method = genMethod()(code.map(_._1): _*) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala index c9c98b403b56..7ca09ff41d4b 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala @@ -14,7 +14,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class UnusedLocalVariablesTest extends BytecodeTesting { - override def compilerArgs = "-Yopt:unreachable-code" + override def compilerArgs = "-opt:unreachable-code" import compiler._ @Test diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index b6e8d4fbf2d7..de18dec34434 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -12,7 +12,7 @@ import scala.tools.testing.BytecodeTesting._ @RunWith(classOf[JUnit4]) class PatmatBytecodeTest extends BytecodeTesting { - val optCompiler = cached("optCompiler", () => newCompiler(extraArgs = "-Yopt:l:project")) + val optCompiler = cached("optCompiler", () => newCompiler(extraArgs = "-opt:l:project")) import compiler._ diff --git a/test/pending/jvm/constant-optimization/Foo_1.flags b/test/pending/jvm/constant-optimization/Foo_1.flags index 9691c0985d52..432f01c02d30 100644 --- a/test/pending/jvm/constant-optimization/Foo_1.flags +++ b/test/pending/jvm/constant-optimization/Foo_1.flags @@ -1 +1 @@ -// constant otimization not there yet, -Yopt:nullness-tracking not enough. +// constant otimization not there yet, -opt:nullness-tracking not enough. From 54dff8120786501f0e273166869b73b5f3accd17 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 25 May 2016 11:55:47 -0700 Subject: [PATCH 063/153] SI-9382 Privatize enhanced x in Tuple2Zipped.Ops Probably there should be an Abide rule to avoid leaking the "underlying value" of a value class. The spec or SIP defines "underlying type" but doesn't mention the underlying value. The argument for concealing the member is that it is redundant and makes autocompletion results harder to read. Also, possibly an additional implicit might want to add a member so-named. --- src/library/scala/runtime/Tuple2Zipped.scala | 2 +- src/library/scala/runtime/Tuple3Zipped.scala | 2 +- test/files/neg/t9382.check | 10 ++++++++++ test/files/neg/t9382.scala | 6 ++++++ 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 test/files/neg/t9382.check create mode 100644 test/files/neg/t9382.scala diff --git a/src/library/scala/runtime/Tuple2Zipped.scala b/src/library/scala/runtime/Tuple2Zipped.scala index 15331d416043..41ed9644aa28 100644 --- a/src/library/scala/runtime/Tuple2Zipped.scala +++ b/src/library/scala/runtime/Tuple2Zipped.scala @@ -115,7 +115,7 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 } object Tuple2Zipped { - final class Ops[T1, T2](val x: (T1, T2)) extends AnyVal { + final class Ops[T1, T2](private val x: (T1, T2)) extends AnyVal { def invert[El1, CC1[X] <: TraversableOnce[X], El2, CC2[X] <: TraversableOnce[X], That] (implicit w1: T1 <:< CC1[El1], w2: T2 <:< CC2[El2], diff --git a/src/library/scala/runtime/Tuple3Zipped.scala b/src/library/scala/runtime/Tuple3Zipped.scala index 62bee5ff0e66..89f401ea8000 100644 --- a/src/library/scala/runtime/Tuple3Zipped.scala +++ b/src/library/scala/runtime/Tuple3Zipped.scala @@ -123,7 +123,7 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers } object Tuple3Zipped { - final class Ops[T1, T2, T3](val x: (T1, T2, T3)) extends AnyVal { + final class Ops[T1, T2, T3](private val x: (T1, T2, T3)) extends AnyVal { def invert[El1, CC1[X] <: TraversableOnce[X], El2, CC2[X] <: TraversableOnce[X], El3, CC3[X] <: TraversableOnce[X], That] (implicit w1: T1 <:< CC1[El1], w2: T2 <:< CC2[El2], diff --git a/test/files/neg/t9382.check b/test/files/neg/t9382.check new file mode 100644 index 000000000000..93bf48926ab0 --- /dev/null +++ b/test/files/neg/t9382.check @@ -0,0 +1,10 @@ +t9382.scala:3: error: value x is not a member of (List[Int], List[Int]) + def f = (List(1,2,3), List(4,5,6)).x + ^ +t9382.scala:4: error: value x is not a member of (List[Int], List[Int], List[Int]) + def g = (List(1,2,3), List(4,5,6), List(7,8,9)).x + ^ +t9382.scala:5: error: value x is not a member of (Int, Int) + def huh = (1,2).x + ^ +three errors found diff --git a/test/files/neg/t9382.scala b/test/files/neg/t9382.scala new file mode 100644 index 000000000000..19703525e4a7 --- /dev/null +++ b/test/files/neg/t9382.scala @@ -0,0 +1,6 @@ + +trait T { + def f = (List(1,2,3), List(4,5,6)).x + def g = (List(1,2,3), List(4,5,6), List(7,8,9)).x + def huh = (1,2).x +} From 3873fcfcbcc6c7f0c1660c18e45b265170580546 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 24 May 2016 14:09:48 +0100 Subject: [PATCH 064/153] Fully qualify types in REPL generated code --- .../scala/tools/nsc/interpreter/IMain.scala | 6 +- .../tools/nsc/interpreter/ReplStrings.scala | 2 +- .../tools/nsc/interpreter/Scripted.scala | 26 +- ...repl-no-imports-no-predef-classbased.check | 23 ++ ...repl-no-imports-no-predef-classbased.scala | 19 + .../run/repl-no-imports-no-predef-power.check | 29 ++ .../run/repl-no-imports-no-predef-power.scala | 21 + .../files/run/repl-no-imports-no-predef.check | 360 ++++++++++++++++++ .../files/run/repl-no-imports-no-predef.scala | 108 ++++++ test/files/run/repl-parens.scala | 10 +- test/files/run/t7747-repl.check | 6 +- test/files/run/t7747-repl.scala | 6 +- .../tools/nsc/interpreter/ScriptedTest.scala | 19 + 13 files changed, 604 insertions(+), 31 deletions(-) create mode 100644 test/files/run/repl-no-imports-no-predef-classbased.check create mode 100644 test/files/run/repl-no-imports-no-predef-classbased.scala create mode 100644 test/files/run/repl-no-imports-no-predef-power.check create mode 100644 test/files/run/repl-no-imports-no-predef-power.scala create mode 100644 test/files/run/repl-no-imports-no-predef.check create mode 100644 test/files/run/repl-no-imports-no-predef.scala diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index a42a12a6fc5c..a77e6f45f8fb 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -614,7 +614,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends bindRep.compile(s""" |object ${bindRep.evalName} { | var value: $boundType = _ - | def set(x: Any) = value = x.asInstanceOf[$boundType] + | def set(x: _root_.scala.Any) = value = x.asInstanceOf[$boundType] |} """.stripMargin ) @@ -882,7 +882,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } class ClassBasedWrapper extends Wrapper { - def preambleHeader = "class %s extends Serializable { " + def preambleHeader = "class %s extends _root_.java.io.Serializable { " /** Adds an object that instantiates the outer wrapping class. */ def postamble = s""" @@ -915,7 +915,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val preamble = """ |object %s { | %s - | lazy val %s: String = %s { + | lazy val %s: _root_.java.lang.String = %s { | %s | ("" """.stripMargin.format( diff --git a/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala b/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala index bf7508cb4e72..87ca05600c1f 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala @@ -34,7 +34,7 @@ trait ReplStrings { "\"" + string2code(str) + "\"" def any2stringOf(x: Any, maxlen: Int) = - "scala.runtime.ScalaRunTime.replStringOf(%s, %s)".format(x, maxlen) + "_root_.scala.runtime.ScalaRunTime.replStringOf(%s, %s)".format(x, maxlen) // no escaped or nested quotes private[this] val inquotes = """(['"])(.*?)\1""".r diff --git a/src/repl/scala/tools/nsc/interpreter/Scripted.scala b/src/repl/scala/tools/nsc/interpreter/Scripted.scala index 25d359bc0e1a..6aef486957d5 100644 --- a/src/repl/scala/tools/nsc/interpreter/Scripted.scala +++ b/src/repl/scala/tools/nsc/interpreter/Scripted.scala @@ -42,7 +42,7 @@ class Scripted(@BeanProperty val factory: ScriptEngineFactory, settings: Setting val adjusted = contextual.map { n => val valname = n.decodedName s"""def `$valname` = $ctx.`$valname` - def `${valname}_=`(x: Object) = $ctx.`$valname` = x""" + def `${valname}_=`(x: _root_.java.lang.Object) = $ctx.`$valname` = x""" }.mkString(preamble, "\n", "\n") ComputedImports(header, adjusted, trailer, path) } @@ -87,30 +87,32 @@ class Scripted(@BeanProperty val factory: ScriptEngineFactory, settings: Setting if (intp.isInitializeComplete) { // compile the dynamic ScriptContext object holder - scriptContextRep compile s""" - |import javax.script._ + val ctxRes = scriptContextRep compile s""" + |import _root_.javax.script._ |object ${scriptContextRep.evalName} { | var value: ScriptContext = _ - | def set(x: Any) = value = x.asInstanceOf[ScriptContext] + | def set(x: _root_.scala.Any) = value = x.asInstanceOf[ScriptContext] |} """.stripMargin + if (!ctxRes) throw new ScriptException("Failed to compile ctx") dynamicContext = getContext // Bridge dynamic references and script context - intp compileString s""" + val dynRes = intp compileString s""" |package scala.tools.nsc.interpreter - |import language.dynamics - |import javax.script._, ScriptContext.ENGINE_SCOPE - |object dynamicBindings extends Dynamic { + |import _root_.scala.language.dynamics + |import _root_.javax.script._, ScriptContext.ENGINE_SCOPE + |object dynamicBindings extends _root_.scala.Dynamic { | def context: ScriptContext = ${ scriptContextRep.evalPath }.value | // $ctx.x retrieves the attribute x - | def selectDynamic(field: String): Object = context.getAttribute(field) + | def selectDynamic(field: _root_.java.lang.String): _root_.java.lang.Object = context.getAttribute(field) | // $ctx.x = v - | def updateDynamic(field: String)(value: Object) = context.setAttribute(field, value, ENGINE_SCOPE) + | def updateDynamic(field: _root_.java.lang.String)(value: _root_.java.lang.Object) = context.setAttribute(field, value, ENGINE_SCOPE) |} |""".stripMargin + if (!dynRes) throw new ScriptException("Failed to compile dynamicBindings") intp beQuietDuring { - intp interpret s"val $ctx: scala.tools.nsc.interpreter.dynamicBindings.type = scala.tools.nsc.interpreter.dynamicBindings" + intp interpret s"val $ctx: _root_.scala.tools.nsc.interpreter.dynamicBindings.type = _root_.scala.tools.nsc.interpreter.dynamicBindings" intp bind ("$engine" -> (this: ScriptEngine with Compilable)) } } @@ -292,7 +294,7 @@ object Scripted { case _ => null } - def getProgram(statements: String*): String = statements.mkString("object Main extends App {\n\t", "\n\t", "\n}") + def getProgram(statements: String*): String = statements.mkString("object Main extends _root_.scala.App {\n\t", "\n\t", "\n}") def getScriptEngine: ScriptEngine = { val settings = new Settings() diff --git a/test/files/run/repl-no-imports-no-predef-classbased.check b/test/files/run/repl-no-imports-no-predef-classbased.check new file mode 100644 index 000000000000..a796600061c4 --- /dev/null +++ b/test/files/run/repl-no-imports-no-predef-classbased.check @@ -0,0 +1,23 @@ + +scala> case class K(s: java.lang.String) +defined class K + +scala> class C { implicit val k: K = K("OK?"); override def toString = "C(" + k.toString + ")" } +defined class C + +scala> val c = new C +c: C = C(K(OK?)) + +scala> import c.k +import c.k + +scala> scala.Predef.implicitly[K] +res0: K = K(OK?) + +scala> val k = 42 +k: Int = 42 + +scala> k // was K(OK?) +res1: Int = 42 + +scala> :quit diff --git a/test/files/run/repl-no-imports-no-predef-classbased.scala b/test/files/run/repl-no-imports-no-predef-classbased.scala new file mode 100644 index 000000000000..86bd07b2f2ed --- /dev/null +++ b/test/files/run/repl-no-imports-no-predef-classbased.scala @@ -0,0 +1,19 @@ +object Test extends scala.tools.partest.ReplTest { + + override def transformSettings(settings: scala.tools.nsc.Settings) = { + settings.noimports.value = true + settings.nopredef.value = true + settings.Yreplclassbased.value = true + settings + } + + def code = """ +case class K(s: java.lang.String) +class C { implicit val k: K = K("OK?"); override def toString = "C(" + k.toString + ")" } +val c = new C +import c.k +scala.Predef.implicitly[K] +val k = 42 +k // was K(OK?) +""" +} diff --git a/test/files/run/repl-no-imports-no-predef-power.check b/test/files/run/repl-no-imports-no-predef-power.check new file mode 100644 index 000000000000..0d4a30b8e3b3 --- /dev/null +++ b/test/files/run/repl-no-imports-no-predef-power.check @@ -0,0 +1,29 @@ + +scala> :power +Power mode enabled. :phase is at typer. +import scala.tools.nsc._, intp.global._, definitions._ +Try :help or completions for vals._ and power._ + +scala> // guarding against "error: reference to global is ambiguous" + +scala> global.emptyValDef // "it is imported twice in the same scope by ..." +warning: there was one deprecation warning; re-run with -deprecation for details +res0: $r.global.noSelfType.type = private val _ = _ + +scala> val tp = ArrayClass[scala.util.Random] // magic with tags +warning: there was one feature warning; re-run with -feature for details +tp: $r.global.Type = Array[scala.util.Random] + +scala> tp.memberType(Array_apply) // evidence +res1: $r.global.Type = (i: Int)scala.util.Random + +scala> val m = LIT(10) // treedsl +m: $r.treedsl.global.Literal = 10 + +scala> typed(m).tpe // typed is in scope +res2: $r.treedsl.global.Type = Int(10) + +scala> """escaping is hard, m'kah""" +res3: String = escaping is hard, m'kah + +scala> :quit diff --git a/test/files/run/repl-no-imports-no-predef-power.scala b/test/files/run/repl-no-imports-no-predef-power.scala new file mode 100644 index 000000000000..24d4dceef288 --- /dev/null +++ b/test/files/run/repl-no-imports-no-predef-power.scala @@ -0,0 +1,21 @@ +object Test extends scala.tools.partest.ReplTest { + + override def transformSettings(settings: scala.tools.nsc.Settings) = { + settings.noimports.value = true + settings.nopredef.value = true + settings + } + + def tripleQuote(s: String) = "\"\"\"" + s + "\"\"\"" + + def code = s""" +:power +// guarding against "error: reference to global is ambiguous" +global.emptyValDef // "it is imported twice in the same scope by ..." +val tp = ArrayClass[scala.util.Random] // magic with tags +tp.memberType(Array_apply) // evidence +val m = LIT(10) // treedsl +typed(m).tpe // typed is in scope +${tripleQuote("escaping is hard, m'kah")} + """.trim +} diff --git a/test/files/run/repl-no-imports-no-predef.check b/test/files/run/repl-no-imports-no-predef.check new file mode 100644 index 000000000000..c2c8d21c0a2c --- /dev/null +++ b/test/files/run/repl-no-imports-no-predef.check @@ -0,0 +1,360 @@ + +scala> 1 +res0: Int = 1 + +scala> 1.0 +res1: Double = 1.0 + +scala> () + +scala> "abc" +res3: String = abc + +scala> (1, 2) +res4: (Int, Int) = (1,2) + +scala> + +scala> { import scala.Predef.ArrowAssoc; 1 -> 2 } +res5: (Int, Int) = (1,2) + +scala> { import scala.Predef.ArrowAssoc; 1 → 2 } +res6: (Int, Int) = (1,2) + +scala> 1 -> 2 +:12: error: value -> is not a member of Int + 1 -> 2 + ^ + +scala> 1 → 2 +:12: error: value → is not a member of Int + 1 → 2 + ^ + +scala> + +scala> val answer = 42 +answer: Int = 42 + +scala> { import scala.StringContext; s"answer: $answer" } +res9: String = answer: 42 + +scala> s"answer: $answer" +:13: error: not found: value StringContext + s"answer: $answer" + ^ + +scala> + +scala> "abc" + true +res11: String = abctrue + +scala> + +scala> { import scala.Predef.any2stringadd; true + "abc" } +res12: String = trueabc + +scala> true + "abc" +:12: error: value + is not a member of Boolean + true + "abc" + ^ + +scala> + +scala> var x = 10 +x: Int = 10 + +scala> var y = 11 +y: Int = 11 + +scala> x = 12 +x: Int = 12 + +scala> y = 13 +y: Int = 13 + +scala> + +scala> 2 ; 3 +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 2 ;; + ^ +res14: Int = 3 + +scala> { 2 ; 3 } +:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + { 2 ; 3 } + ^ +res15: Int = 3 + +scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def +bippy = { + 1 + + 2 + + 3 } ; bippy+88+11 +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def + ^ +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def + ^ +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def + ^ +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def + ^ +defined object Cow +defined class Moo +bippy: Int +res16: Int = 105 + +scala> + +scala> object Bovine { var x: scala.List[_] = null } ; case class Ruminant(x: scala.Int) ; bippy * bippy * bippy +defined object Bovine +defined class Ruminant +res17: Int = 216 + +scala> Bovine.x = scala.List(Ruminant(5), Cow, new Moo) +Bovine.x: List[Any] = List(Ruminant(5), Cow, Moooooo) + +scala> Bovine.x +res18: List[Any] = List(Ruminant(5), Cow, Moooooo) + +scala> + +scala> (2) +res19: Int = 2 + +scala> (2 + 2) +res20: Int = 4 + +scala> ((2 + 2)) +res21: Int = 4 + +scala> ((2 + 2)) +res22: Int = 4 + +scala> ( (2 + 2)) +res23: Int = 4 + +scala> ( (2 + 2 ) ) +res24: Int = 4 + +scala> 5 ; ( (2 + 2 ) ) ; ((5)) +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; ( (2 + 2 ) ) ;; + ^ +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; ( (2 + 2 ) ) ;; + ^ +res25: Int = 5 + +scala> (((2 + 2)), ((2 + 2))) +res26: (Int, Int) = (4,4) + +scala> (((2 + 2)), ((2 + 2)), 2) +res27: (Int, Int, Int) = (4,4,2) + +scala> (((((2 + 2)), ((2 + 2)), 2).productIterator ++ scala.Iterator(3)).mkString) +res28: String = 4423 + +scala> + +scala> 55 ; ((2 + 2)) ; (1, 2, 3) +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ; ((2 + 2)) ;; + ^ +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ; ((2 + 2)) ;; + ^ +res29: (Int, Int, Int) = (1,2,3) + +scala> 55 ; (x: scala.Int) => x + 1 ; () => ((5)) +:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ; (x: scala.Int) => x + 1 ;; + ^ +res30: () => Int = + +scala> + +scala> () => 5 +res31: () => Int = + +scala> 55 ; () => 5 +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ;; + ^ +res32: () => Int = + +scala> () => { class X ; new X } +res33: () => AnyRef = + +scala> + +scala> def foo(x: scala.Int)(y: scala.Int)(z: scala.Int) = x+y+z +foo: (x: Int)(y: Int)(z: Int)Int + +scala> foo(5)(10)(15)+foo(5)(10)(15) +res34: Int = 60 + +scala> + +scala> scala.List(1) ++ scala.List('a') +res35: List[AnyVal] = List(1, a) + +scala> + +scala> :paste < EOF +// Entering paste mode (EOF to finish) + +class C { def c = 42 } +EOF + +// Exiting paste mode, now interpreting. + +defined class C + +scala> new C().c +res36: Int = 42 + +scala> :paste <| EOF +// Entering paste mode (EOF to finish) + +class D { def d = 42 } +EOF + +// Exiting paste mode, now interpreting. + +defined class D + +scala> new D().d +res37: Int = 42 + +scala> + +scala> :paste < EOF +// Entering paste mode (EOF to finish) + +class Dingus +{ + private val x = 5 + def y = Dingus.x * 2 +} +object Dingus +{ + private val x = 55 +} +EOF + +// Exiting paste mode, now interpreting. + +defined class Dingus +defined object Dingus + +scala> val x = (new Dingus).y +x: Int = 110 + +scala> + +scala> val x1 = 1 +x1: Int = 1 + +scala> val x2 = 2 +x2: Int = 2 + +scala> val x3 = 3 +x3: Int = 3 + +scala> case class BippyBungus() +defined class BippyBungus + +scala> x1 + x2 + x3 +res38: Int = 6 + +scala> :reset +Resetting interpreter state. +Forgetting this session history: + +1 +1.0 +() +"abc" +(1, 2) +{ import scala.Predef.ArrowAssoc; 1 -> 2 } +{ import scala.Predef.ArrowAssoc; 1 → 2 } +val answer = 42 +{ import scala.StringContext; s"answer: $answer" } +"abc" + true +{ import scala.Predef.any2stringadd; true + "abc" } +var x = 10 +var y = 11 +x = 12 +y = 13 +2 ; 3 +{ 2 ; 3 } +5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def +bippy = { + 1 + + 2 + + 3 } ; bippy+88+11 +object Bovine { var x: scala.List[_] = null } ; case class Ruminant(x: scala.Int) ; bippy * bippy * bippy +Bovine.x = scala.List(Ruminant(5), Cow, new Moo) +Bovine.x +(2) +(2 + 2) +((2 + 2)) + ((2 + 2)) + ( (2 + 2)) + ( (2 + 2 ) ) +5 ; ( (2 + 2 ) ) ; ((5)) +(((2 + 2)), ((2 + 2))) +(((2 + 2)), ((2 + 2)), 2) +(((((2 + 2)), ((2 + 2)), 2).productIterator ++ scala.Iterator(3)).mkString) +55 ; ((2 + 2)) ; (1, 2, 3) +55 ; (x: scala.Int) => x + 1 ; () => ((5)) +() => 5 +55 ; () => 5 +() => { class X ; new X } +def foo(x: scala.Int)(y: scala.Int)(z: scala.Int) = x+y+z +foo(5)(10)(15)+foo(5)(10)(15) +scala.List(1) ++ scala.List('a') +new C().c +new D().d +val x = (new Dingus).y +val x1 = 1 +val x2 = 2 +val x3 = 3 +case class BippyBungus() +x1 + x2 + x3 + +Forgetting all expression results and named terms: $intp, BippyBungus, Bovine, Cow, Dingus, Ruminant, answer, bippy, foo, x, x1, x2, x3, y +Forgetting defined types: BippyBungus, C, D, Dingus, Moo, Ruminant + +scala> x1 + x2 + x3 +:12: error: not found: value x1 + x1 + x2 + x3 + ^ +:12: error: not found: value x2 + x1 + x2 + x3 + ^ +:12: error: not found: value x3 + x1 + x2 + x3 + ^ + +scala> val x1 = 4 +x1: Int = 4 + +scala> new BippyBungus +:12: error: not found: type BippyBungus + new BippyBungus + ^ + +scala> class BippyBungus() { def f = 5 } +defined class BippyBungus + +scala> { new BippyBungus ; x1 } +res2: Int = 4 + +scala> :quit diff --git a/test/files/run/repl-no-imports-no-predef.scala b/test/files/run/repl-no-imports-no-predef.scala new file mode 100644 index 000000000000..39f43c534dc6 --- /dev/null +++ b/test/files/run/repl-no-imports-no-predef.scala @@ -0,0 +1,108 @@ +object Test extends scala.tools.partest.ReplTest { + + override def transformSettings(settings: scala.tools.nsc.Settings) = { + settings.noimports.value = true + settings.nopredef.value = true + settings + } + + // replace indylambda function names by + override def normalize(s: String) = """\$\$Lambda.*""".r.replaceAllIn(s, "") + + def code = """ +1 +1.0 +() +"abc" +(1, 2) + +{ import scala.Predef.ArrowAssoc; 1 -> 2 } +{ import scala.Predef.ArrowAssoc; 1 → 2 } +1 -> 2 +1 → 2 + +val answer = 42 +{ import scala.StringContext; s"answer: $answer" } +s"answer: $answer" + +"abc" + true + +{ import scala.Predef.any2stringadd; true + "abc" } +true + "abc" + +var x = 10 +var y = 11 +x = 12 +y = 13 + +2 ; 3 +{ 2 ; 3 } +5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def +bippy = { + 1 + + 2 + + 3 } ; bippy+88+11 + +object Bovine { var x: scala.List[_] = null } ; case class Ruminant(x: scala.Int) ; bippy * bippy * bippy +Bovine.x = scala.List(Ruminant(5), Cow, new Moo) +Bovine.x + +(2) +(2 + 2) +((2 + 2)) + ((2 + 2)) + ( (2 + 2)) + ( (2 + 2 ) ) +5 ; ( (2 + 2 ) ) ; ((5)) +(((2 + 2)), ((2 + 2))) +(((2 + 2)), ((2 + 2)), 2) +(((((2 + 2)), ((2 + 2)), 2).productIterator ++ scala.Iterator(3)).mkString) + +55 ; ((2 + 2)) ; (1, 2, 3) +55 ; (x: scala.Int) => x + 1 ; () => ((5)) + +() => 5 +55 ; () => 5 +() => { class X ; new X } + +def foo(x: scala.Int)(y: scala.Int)(z: scala.Int) = x+y+z +foo(5)(10)(15)+foo(5)(10)(15) + +scala.List(1) ++ scala.List('a') + +:paste < EOF +class C { def c = 42 } +EOF +new C().c +:paste <| EOF +class D { def d = 42 } +EOF +new D().d + +:paste < EOF +class Dingus +{ + private val x = 5 + def y = Dingus.x * 2 +} +object Dingus +{ + private val x = 55 +} +EOF +val x = (new Dingus).y + +val x1 = 1 +val x2 = 2 +val x3 = 3 +case class BippyBungus() +x1 + x2 + x3 +:reset +x1 + x2 + x3 +val x1 = 4 +new BippyBungus +class BippyBungus() { def f = 5 } +{ new BippyBungus ; x1 } + +""" +} diff --git a/test/files/run/repl-parens.scala b/test/files/run/repl-parens.scala index 43e642a806e4..613bb6f6afb2 100644 --- a/test/files/run/repl-parens.scala +++ b/test/files/run/repl-parens.scala @@ -1,6 +1,9 @@ import scala.tools.partest.ReplTest object Test extends ReplTest { + // replace indylambda function names by + override def normalize(s: String) = """\$\$Lambda.*""".r.replaceAllIn(s, "") + def code = """ (2) (2 + 2) @@ -26,11 +29,4 @@ foo(5)(10)(15)+foo(5)(10)(15) List(1) ++ List('a') """.trim - - // replace indylambda function names by - override def eval() = { - val lines = super.eval - val r = """\$\$Lambda.*""".r - lines.map(l => r.replaceAllIn(l, "")) - } } diff --git a/test/files/run/t7747-repl.check b/test/files/run/t7747-repl.check index d698ea668d5a..c5e92e9d796d 100644 --- a/test/files/run/t7747-repl.check +++ b/test/files/run/t7747-repl.check @@ -246,12 +246,12 @@ scala> case class Bingo() defined class Bingo scala> List(BippyBups(), PuppyPups(), Bingo()) // show -class $read extends Serializable { +class $read extends _root_.java.io.Serializable { def () = { super.; () }; - class $iw extends Serializable { + class $iw extends _root_.java.io.Serializable { def () = { super.; () @@ -262,7 +262,7 @@ class $read extends Serializable { import $line45.$read.INSTANCE.$iw.$iw.PuppyPups; import $line46.$read.INSTANCE.$iw.$iw.Bingo; import $line46.$read.INSTANCE.$iw.$iw.Bingo; - class $iw extends Serializable { + class $iw extends _root_.java.io.Serializable { def () = { super.; () diff --git a/test/files/run/t7747-repl.scala b/test/files/run/t7747-repl.scala index 9b2d1c40be01..c6a7e419aa14 100644 --- a/test/files/run/t7747-repl.scala +++ b/test/files/run/t7747-repl.scala @@ -9,11 +9,7 @@ object Test extends ReplTest { } // replace indylambda function names by - override def eval() = { - val lines = super.eval - val r = """\$Lambda.*""".r - lines.map(l => r.replaceAllIn(l, "")) - } + override def normalize(s: String) = """\$Lambda.*""".r.replaceAllIn(s, "") def code = """ |var x = 10 diff --git a/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala b/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala index a8dc8eb3e071..01d17110d698 100644 --- a/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala +++ b/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala @@ -13,6 +13,14 @@ class ScriptedTest { // same as by service discovery //new ScriptEngineManager().getEngineByName("scala").asInstanceOf[ScriptEngine with Compilable] + // scripted, but also -Yno-predef -Yno-imports + def scriptedNoNothing: ScriptEngine with Compilable = { + val settings = new Settings() + settings.noimports.value = true + settings.nopredef.value = true + Scripted(settings = settings) + } + @Test def eval() = { val engine = scripted engine.put("foo","bar") @@ -24,6 +32,17 @@ class ScriptedTest { assert("barbar" == c.eval()) assert("bazbaz" == c.eval(bindings)) } + @Test def evalNoNothing() = { + val engine = scriptedNoNothing + engine.put("foo","bar") + assert("bar" == engine.eval("foo")) + val bindings = engine.createBindings() + bindings.put("foo","baz") + assert("baz" == engine.eval("foo", bindings)) + val c = engine.compile("import scala.Predef.augmentString ; def f = foo.asInstanceOf[java.lang.String] ; f * 2") + assert("barbar" == c.eval()) + assert("bazbaz" == c.eval(bindings)) + } @Test def `SI-7933 multiple eval compiled script`() = { val engine = scripted val init = """val i = new java.util.concurrent.atomic.AtomicInteger""" From 0b79f4bf586268947b3e72750413e7106c4ad46e Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 26 May 2016 13:00:50 -0700 Subject: [PATCH 065/153] SI-9382 Zippy clean-up in aisle 2 & 3 Consolated JUnit tests and heeded comment about private def and code beauty. --- src/library/scala/runtime/Tuple2Zipped.scala | 39 +++++------ src/library/scala/runtime/Tuple3Zipped.scala | 46 +++++++------ test/files/run/tuple-zipped.scala | 41 ----------- .../collection/immutable/StreamTest.scala | 16 ----- test/junit/scala/runtime/ZippedTest.scala | 68 +++++++++++++++++++ 5 files changed, 113 insertions(+), 97 deletions(-) delete mode 100644 test/files/run/tuple-zipped.scala create mode 100644 test/junit/scala/runtime/ZippedTest.scala diff --git a/src/library/scala/runtime/Tuple2Zipped.scala b/src/library/scala/runtime/Tuple2Zipped.scala index 41ed9644aa28..52dd1da09e82 100644 --- a/src/library/scala/runtime/Tuple2Zipped.scala +++ b/src/library/scala/runtime/Tuple2Zipped.scala @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2002-2016, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -34,14 +34,15 @@ object ZippedTraversable2 { } final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1, Repr1], IterableLike[El2, Repr2])) extends AnyVal with ZippedTraversable2[El1, El2] { - // This would be better as "private def coll1 = colls._1" but - // SI-6215 precludes private methods in value classes. + private def coll1 = colls._1 + private def coll2 = colls._2 + def map[B, To](f: (El1, El2) => B)(implicit cbf: CBF[Repr1, B, To]): To = { - val b = cbf(colls._1.repr) - b.sizeHint(colls._1) - val elems2 = colls._2.iterator + val b = cbf(coll1.repr) + b.sizeHint(coll1) + val elems2 = coll2.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext) b += f(el1, elems2.next()) else @@ -52,10 +53,10 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 } def flatMap[B, To](f: (El1, El2) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = { - val b = cbf(colls._1.repr) - val elems2 = colls._2.iterator + val b = cbf(coll1.repr) + val elems2 = coll2.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext) b ++= f(el1, elems2.next()) else @@ -66,11 +67,11 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 } def filter[To1, To2](f: (El1, El2) => Boolean)(implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2]): (To1, To2) = { - val b1 = cbf1(colls._1.repr) - val b2 = cbf2(colls._2.repr) - val elems2 = colls._2.iterator + val b1 = cbf1(coll1.repr) + val b2 = cbf2(coll2.repr) + val elems2 = coll2.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext) { val el2 = elems2.next() if (f(el1, el2)) { @@ -85,9 +86,9 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 } def exists(@deprecatedName('f) p: (El1, El2) => Boolean): Boolean = { - val elems2 = colls._2.iterator + val elems2 = coll2.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext) { if (p(el1, elems2.next())) return true @@ -101,9 +102,9 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 !exists((x, y) => !p(x, y)) def foreach[U](f: (El1, El2) => U): Unit = { - val elems2 = colls._2.iterator + val elems2 = coll2.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext) f(el1, elems2.next()) else @@ -111,7 +112,7 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1 } } - override def toString = "(%s, %s).zipped".format(colls._1.toString, colls._2.toString) + override def toString = s"($coll1, $coll2).zipped" } object Tuple2Zipped { diff --git a/src/library/scala/runtime/Tuple3Zipped.scala b/src/library/scala/runtime/Tuple3Zipped.scala index 89f401ea8000..a4a86f8e55b0 100644 --- a/src/library/scala/runtime/Tuple3Zipped.scala +++ b/src/library/scala/runtime/Tuple3Zipped.scala @@ -34,12 +34,16 @@ object ZippedTraversable3 { final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (TraversableLike[El1, Repr1], IterableLike[El2, Repr2], IterableLike[El3, Repr3])) extends AnyVal with ZippedTraversable3[El1, El2, El3] { + private def coll1 = colls._1 + private def coll2 = colls._2 + private def coll3 = colls._3 + def map[B, To](f: (El1, El2, El3) => B)(implicit cbf: CBF[Repr1, B, To]): To = { - val b = cbf(colls._1.repr) - val elems2 = colls._2.iterator - val elems3 = colls._3.iterator + val b = cbf(coll1.repr) + val elems2 = coll2.iterator + val elems3 = coll3.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext && elems3.hasNext) b += f(el1, elems2.next(), elems3.next()) else @@ -49,11 +53,11 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers } def flatMap[B, To](f: (El1, El2, El3) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = { - val b = cbf(colls._1.repr) - val elems2 = colls._2.iterator - val elems3 = colls._3.iterator + val b = cbf(coll1.repr) + val elems2 = coll2.iterator + val elems3 = coll3.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext && elems3.hasNext) b ++= f(el1, elems2.next(), elems3.next()) else @@ -66,14 +70,14 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2], cbf3: CBF[Repr3, El3, To3]): (To1, To2, To3) = { - val b1 = cbf1(colls._1.repr) - val b2 = cbf2(colls._2.repr) - val b3 = cbf3(colls._3.repr) - val elems2 = colls._2.iterator - val elems3 = colls._3.iterator + val b1 = cbf1(coll1.repr) + val b2 = cbf2(coll2.repr) + val b3 = cbf3(coll3.repr) + val elems2 = coll2.iterator + val elems3 = coll3.iterator def result = (b1.result(), b2.result(), b3.result()) - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext && elems3.hasNext) { val el2 = elems2.next() val el3 = elems3.next() @@ -91,10 +95,10 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers } def exists(@deprecatedName('f) p: (El1, El2, El3) => Boolean): Boolean = { - val elems2 = colls._2.iterator - val elems3 = colls._3.iterator + val elems2 = coll2.iterator + val elems3 = coll3.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext && elems3.hasNext) { if (p(el1, elems2.next(), elems3.next())) return true @@ -108,10 +112,10 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers !exists((x, y, z) => !p(x, y, z)) def foreach[U](f: (El1, El2, El3) => U): Unit = { - val elems2 = colls._2.iterator - val elems3 = colls._3.iterator + val elems2 = coll2.iterator + val elems3 = coll3.iterator - for (el1 <- colls._1) { + for (el1 <- coll1) { if (elems2.hasNext && elems3.hasNext) f(el1, elems2.next(), elems3.next()) else @@ -119,7 +123,7 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers } } - override def toString: String = "(%s, %s, %s).zipped".format(colls._1.toString, colls._2.toString, colls._3.toString) + override def toString = s"($coll1, $coll2, $coll3).zipped" } object Tuple3Zipped { diff --git a/test/files/run/tuple-zipped.scala b/test/files/run/tuple-zipped.scala deleted file mode 100644 index 37ac52977f35..000000000000 --- a/test/files/run/tuple-zipped.scala +++ /dev/null @@ -1,41 +0,0 @@ - -import scala.language.postfixOps - -object Test { - val xs1 = List.range(1, 100) - val xs2 = xs1.view - val xs3 = xs1 take 10 - val ss1 = Stream from 1 - val ss2 = ss1.view - val ss3 = ss1 take 10 - val as1 = 1 to 100 toArray - val as2 = as1.view - val as3 = as1 take 10 - - def xss1 = List[Seq[Int]](xs1, xs2, xs3, ss1, ss2, ss3, as1, as2, as3) - def xss2 = List[Seq[Int]](xs1, xs2, xs3, ss3, as1, as2, as3) // no infinities - def xss3 = List[Seq[Int]](xs2, xs3, ss3, as1) // representative sampling - - def main(args: Array[String]): Unit = { - for (cc1 <- xss1 ; cc2 <- xss2) { - val sum1 = (cc1, cc2).zipped map { case (x, y) => x + y } sum - val sum2 = (cc1, cc2).zipped map (_ + _) sum - - assert(sum1 == sum2) - } - - for (cc1 <- xss1 ; cc2 <- xss2 ; cc3 <- xss3) { - val sum1 = (cc1, cc2, cc3).zipped map { case (x, y, z) => x + y + z } sum - val sum2 = (cc1, cc2, cc3).zipped map (_ + _ + _) sum - - assert(sum1 == sum2) - } - - assert((ss1, ss1).zipped exists ((x, y) => true)) - assert((ss1, ss1, ss1).zipped exists ((x, y, z) => true)) - - assert(!(ss1, ss2, 1 to 3).zipped.exists(_ + _ + _ > 100000)) - assert((1 to 3, ss1, ss2).zipped.forall(_ + _ + _ > 0)) - assert((ss1, 1 to 3, ss2).zipped.map(_ + _ + _).size == 3) - } -} diff --git a/test/junit/scala/collection/immutable/StreamTest.scala b/test/junit/scala/collection/immutable/StreamTest.scala index 1b257aabc452..fad4e502eba1 100644 --- a/test/junit/scala/collection/immutable/StreamTest.scala +++ b/test/junit/scala/collection/immutable/StreamTest.scala @@ -107,20 +107,4 @@ class StreamTest { def withFilter_map_properly_lazy_in_tail: Unit = { assertStreamOpLazyInTail(_.withFilter(_ % 2 == 0).map(identity), List(1, 2)) } - - @Test - def test_si9379() { - class Boom { - private var i = -1 - def inc = { - i += 1 - if (i > 1000) throw new NoSuchElementException("Boom! Too many elements!") - i - } - } - val b = new Boom - val s = Stream.continually(b.inc) - // zipped.toString must allow s to short-circuit evaluation - assertTrue((s, s).zipped.toString contains s.toString) - } } diff --git a/test/junit/scala/runtime/ZippedTest.scala b/test/junit/scala/runtime/ZippedTest.scala new file mode 100644 index 000000000000..d3ce4945aa9f --- /dev/null +++ b/test/junit/scala/runtime/ZippedTest.scala @@ -0,0 +1,68 @@ + +package scala.runtime + +import scala.language.postfixOps + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +/** Tests Tuple?Zipped */ +@RunWith(classOf[JUnit4]) +class ZippedTest { + @Test + def crossZipped() { + + val xs1 = List.range(1, 100) + val xs2 = xs1.view + val xs3 = xs1 take 10 + val ss1 = Stream from 1 + val ss2 = ss1.view + val ss3 = ss1 take 10 + val as1 = 1 to 100 toArray + val as2 = as1.view + val as3 = as1 take 10 + + def xss1 = List[Seq[Int]](xs1, xs2, xs3, ss1, ss2, ss3, as1, as2, as3) + def xss2 = List[Seq[Int]](xs1, xs2, xs3, ss3, as1, as2, as3) // no infinities + def xss3 = List[Seq[Int]](xs2, xs3, ss3, as1) // representative sampling + + for (cc1 <- xss1 ; cc2 <- xss2) { + val sum1 = (cc1, cc2).zipped map { case (x, y) => x + y } sum + val sum2 = (cc1, cc2).zipped map (_ + _) sum + + assert(sum1 == sum2) + } + + for (cc1 <- xss1 ; cc2 <- xss2 ; cc3 <- xss3) { + val sum1 = (cc1, cc2, cc3).zipped map { case (x, y, z) => x + y + z } sum + val sum2 = (cc1, cc2, cc3).zipped map (_ + _ + _) sum + + assert(sum1 == sum2) + } + + assert((ss1, ss1).zipped exists ((x, y) => true)) + assert((ss1, ss1, ss1).zipped exists ((x, y, z) => true)) + + assert(!(ss1, ss2, 1 to 3).zipped.exists(_ + _ + _ > 100000)) + assert((1 to 3, ss1, ss2).zipped.forall(_ + _ + _ > 0)) + assert((ss1, 1 to 3, ss2).zipped.map(_ + _ + _).size == 3) + } + + @Test + def test_si9379() { + class Boom { + private var i = -1 + def inc = { + i += 1 + if (i > 1000) throw new NoSuchElementException("Boom! Too many elements!") + i + } + } + val b = new Boom + val s = Stream.continually(b.inc) + // zipped.toString must allow s to short-circuit evaluation + assertTrue((s, s).zipped.toString contains s.toString) + } +} From 100d6374c282d94497ee9f0d4a206d427951c74c Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Sun, 22 May 2016 09:40:54 -0700 Subject: [PATCH 066/153] SI-9789 use quadratic probing in OpenHashMap The original probe sequence, taken from Python's hash table code, is exponential, jumping around in the hash table with poor memory locality. This replaces the probe algorithm with the more conventional quadratic probing. This also adds tests to the benchmarking code using AnyRef keys, which have pseudorandom hash codes (unlike Ints, whose hash code is simply the Int itself). The intensity of the benchmarking is reduced to make the tests complete within 9 hours, by removing unnecessary sampling. --- .../collection/mutable/OpenHashMap.scala | 18 +- .../src/main/scala/benchmark/KeySeq.scala | 24 ++ .../main/scala/benchmark/KeySeqBuilder.scala | 33 +++ .../mutable/OpenHashMapBenchmark.scala | 216 +++++++++++++----- .../mutable/OpenHashMapRunner.scala | 60 ++--- 5 files changed, 257 insertions(+), 94 deletions(-) create mode 100644 test/benchmarks/src/main/scala/benchmark/KeySeq.scala create mode 100644 test/benchmarks/src/main/scala/benchmark/KeySeqBuilder.scala diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala index 5f8f5b9a0a32..c86357efadac 100644 --- a/src/library/scala/collection/mutable/OpenHashMap.scala +++ b/src/library/scala/collection/mutable/OpenHashMap.scala @@ -108,16 +108,13 @@ extends AbstractMap[Key, Value] * @param hash hash value for `key` */ private[this] def findIndex(key: Key, hash: Int): Int = { - var j = hash - var index = hash & mask - var perturb = index + var j = 0 while(table(index) != null && !(table(index).hash == hash && table(index).key == key)){ - j = 5 * j + 1 + perturb - perturb >>= 5 - index = j & mask + j += 1 + index = (index + j) & mask } index } @@ -172,20 +169,17 @@ extends AbstractMap[Key, Value] def get(key : Key) : Option[Value] = { val hash = hashOf(key) - - var j = hash var index = hash & mask - var perturb = index var entry = table(index) + var j = 0 while(entry != null){ if (entry.hash == hash && entry.key == key){ return entry.value } - j = 5 * j + 1 + perturb - perturb >>= 5 - index = j & mask + j += 1 + index = (index + j) & mask entry = table(index) } None diff --git a/test/benchmarks/src/main/scala/benchmark/KeySeq.scala b/test/benchmarks/src/main/scala/benchmark/KeySeq.scala new file mode 100644 index 000000000000..126b92b3b662 --- /dev/null +++ b/test/benchmarks/src/main/scala/benchmark/KeySeq.scala @@ -0,0 +1,24 @@ +package benchmark + +/** A sequence of keys. + * + * Tests of maps and sets require a sequence of keys that can be used + * to add entries and possibly to find them again. + * This type provides such a sequence. + * + * Note that this needn't be a "sequence" in the full sense of [[collection.Seq]], + * particularly in that it needn't extend [[PartialFunction]]. + * + * @tparam K the type of the keys + */ +trait KeySeq[K] { + /** Selects a key by its index in the sequence. + * Repeated calls with the same index return the same key (by reference equality). + * + * @param idx The index to select. Should be non-negative and less than `size`. + */ + def apply(idx: Int): K + + /** The size of this sequence. */ + def size: Int +} diff --git a/test/benchmarks/src/main/scala/benchmark/KeySeqBuilder.scala b/test/benchmarks/src/main/scala/benchmark/KeySeqBuilder.scala new file mode 100644 index 000000000000..95f6c7afd744 --- /dev/null +++ b/test/benchmarks/src/main/scala/benchmark/KeySeqBuilder.scala @@ -0,0 +1,33 @@ +package benchmark + +/** Builder of a [[KeySeq]] + * + * @tparam K the type of the keys + */ +trait KeySeqBuilder[K] { + /** Return a [[KeySeq]] having at least the given size. */ + def build(size: Int): KeySeq[K] +} + +object KeySeqBuilder { + /** Builder of a sequence of `Int` keys. + * Simply maps the sequence index to itself. + */ + implicit object IntKeySeqBuilder extends KeySeqBuilder[Int] { + def build(_size: Int) = new KeySeq[Int] { + def apply(idx: Int) = idx + def size = _size + } + } + + /** Builder of a sequence of `AnyRef` keys. */ + implicit object AnyRefKeySeqBuilder extends KeySeqBuilder[AnyRef] { + def build(_size: Int) = new KeySeq[AnyRef] { + private[this] val arr = new Array[AnyRef](size) + for (i <- 0 until size) arr(i) = new AnyRef() + + def apply(idx: Int) = arr(idx) + def size = _size + } + } +} diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala index 26e26b30654a..64e2244499a7 100644 --- a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapBenchmark.scala @@ -1,14 +1,12 @@ package scala.collection.mutable; -import java.util.concurrent.TimeUnit import org.openjdk.jmh.annotations._ -import org.openjdk.jmh.infra.Blackhole -import org.openjdk.jmh.infra.BenchmarkParams -import org.openjdk.jol.info.GraphLayout -import org.openjdk.jol.info.GraphWalker -import org.openjdk.jol.info.GraphVisitor -import org.openjdk.jmh.infra.IterationParams +import org.openjdk.jmh.infra._ import org.openjdk.jmh.runner.IterationType +import org.openjdk.jol.info.GraphLayout + +import benchmark._ +import java.util.concurrent.TimeUnit /** Utilities for the [[OpenHashMapBenchmark]]. * @@ -16,7 +14,8 @@ import org.openjdk.jmh.runner.IterationType * instead of using the JMH harness, which iterates for a fixed length of time. */ private object OpenHashMapBenchmark { - /** State container for the `put()` bulk calling tests. + + /** Abstract state container for the `put()` bulk calling tests. * * Provides an array of adequately-sized, empty maps to each invocation, * so that hash table allocation won't be done during measurement. @@ -25,10 +24,11 @@ private object OpenHashMapBenchmark { * so that only the GCs caused by the invocation contribute to the measurement. * * Records the memory used by all the maps in the last invocation of each iteration. + * + * @tparam K type of the map keys to be used in the test */ @State(Scope.Thread) - @AuxCounters - class BulkPutState { + private[this] abstract class BulkPutState[K](implicit keyBuilder: KeySeqBuilder[K]) { /** A lower-bound estimate of the number of nanoseconds per `put()` call */ private[this] val nanosPerPut: Double = 5 @@ -39,35 +39,43 @@ private object OpenHashMapBenchmark { private[this] var size: Int = _ /** Total number of entries in all of the `maps` combined. */ - var mapEntries: Int = _ + private[this] var _mapEntries: Int = _ + protected def mapEntries = _mapEntries /** Number of operations performed in the current invocation. */ - var operations: Int = _ + private[this] var _operations: Int = _ + protected def operations = _operations /** Bytes of memory used in the object graphs of all the maps. */ - var memory: Long = _ + private[this] var _memory: Long = _ + protected def memory = _memory + + /** The sequence of keys to store into a map. */ + private[this] var _keys: KeySeq[K] = _ + def keys() = _keys - var maps: Array[OpenHashMap[Int,Int]] = null + var maps: Array[OpenHashMap[K,Int]] = null @Setup def threadSetup(params: BenchmarkParams) { size = params.getParam("size").toInt val n = math.ceil(minNanosPerInvocation / (nanosPerPut * size)).toInt - mapEntries = size * n + _mapEntries = size * n + _keys = keyBuilder.build(size) maps = new Array(n) } @Setup(Level.Iteration) def iterationSetup { - operations = 0 + _operations = 0 } @Setup(Level.Invocation) def setup(params: IterationParams) { - for (i <- 0 until maps.length) maps(i) = new OpenHashMap[Int,Int](size) + for (i <- 0 until maps.length) maps(i) = new OpenHashMap[K,Int](size) if (params.getType == IterationType.MEASUREMENT) { - operations += mapEntries + _operations += _mapEntries System.gc() // clean up after last invocation } } @@ -76,72 +84,124 @@ private object OpenHashMapBenchmark { def iterationTeardown(params: IterationParams) { if (params.getType == IterationType.MEASUREMENT) { // limit to smaller cases to avoid OOM - memory = if (mapEntries <= 1000000) GraphLayout.parseInstance(maps(0), maps.tail).totalSize else 0 + _memory = + if (_mapEntries <= 1000000) GraphLayout.parseInstance(maps(0), maps.tail).totalSize + else 0 } } } - /** State container for the `get()` bulk calling tests. + /** Abstract state container for the `get()` bulk calling tests. * * Provides a thread-scoped map of the expected size. * Performs a GC after loading the map. + * + * @tparam K type of the map keys to be used in the test */ @State(Scope.Thread) - class BulkGetState { - val map = new OpenHashMap[Int,Int].empty + private[this] abstract class BulkGetState[K](implicit keyBuilder: KeySeqBuilder[K]) { + /** The sequence of keys to store into a map. */ + private[this] var _keys: KeySeq[K] = _ + def keys() = _keys + + val map = new OpenHashMap[K,Int].empty /** Load the map with keys from `1` to `size`. */ @Setup def setup(params: BenchmarkParams) { val size = params.getParam("size").toInt - put_Int(map, 1, size) + _keys = keyBuilder.build(size) + put(map, keys, 0, size) System.gc() } } - /** State container for the `get()` bulk calling tests with deleted entries. + /** Abstract state container for the `get()` bulk calling tests with deleted entries. * * Provides a thread-scoped map of the expected size, from which entries have been removed. * Performs a GC after loading the map. + * + * @tparam K type of the map keys to be used in the test */ @State(Scope.Thread) - class BulkRemovedGetState { - val map = new OpenHashMap[Int,Int].empty + private[this] abstract class BulkRemovedGetState[K](implicit keyBuilder: KeySeqBuilder[K]) { + /** The sequence of keys to store into a map. */ + private[this] var _keys: KeySeq[K] = _ + def keys() = _keys + + val map = new OpenHashMap[K,Int].empty /** Load the map with keys from `1` to `size`, removing half of them. */ @Setup def setup(params: BenchmarkParams) { val size = params.getParam("size").toInt - put_remove_Int(map, size) + _keys = keyBuilder.build(size) + put_remove(map, keys) System.gc() } } - /** Put elements into the given map. */ - private def put_Int(map: OpenHashMap[Int,Int], from: Int, to: Int) { + /* In order to use `@AuxCounters` on a class hierarchy (as of JMH 1.11.3), + * it's necessary to place it on the injected (sub)class, and to make the + * counters visible as explicit public members of the that class. JMH doesn't + * scan the ancestor classes for counters. + */ + + @AuxCounters + private class IntBulkPutState extends BulkPutState[Int] { + override def mapEntries = super.mapEntries + override def operations = super.operations + override def memory = super.memory + } + private class IntBulkGetState extends BulkGetState[Int] + private class IntBulkRemovedGetState extends BulkRemovedGetState[Int] + + @AuxCounters + private class AnyRefBulkPutState extends BulkPutState[AnyRef] { + override def mapEntries = super.mapEntries + override def operations = super.operations + override def memory = super.memory + } + private class AnyRefBulkGetState extends BulkGetState[AnyRef] + private class AnyRefBulkRemovedGetState extends BulkRemovedGetState[AnyRef] + + + /** Put entries into the given map. + * Adds entries using a range of keys from the given list. + * + * @param from lowest index in the range of keys to add + * @param to highest index in the range of keys to add, plus one + */ + private[this] def put[K](map: OpenHashMap[K,Int], keys: KeySeq[K], from: Int, to: Int) { var i = from - while (i <= to) { // using a `for` expression instead adds significant overhead - map.put(i, i) + while (i < to) { // using a `for` expression instead adds significant overhead + map.put(keys(i), i) i += 1 } } - /** Put elements into the given map, removing half of them as they're added. + /** Put entries into the given map. + * Adds entries using all of the keys from the given list. + */ + private def put[K](map: OpenHashMap[K,Int], keys: KeySeq[K]): Unit = + put(map, keys, 0, keys.size) + + /** Put entries into the given map, removing half of them as they're added. * - * @param size number of entries to leave in the map on return + * @param keys list of keys to use */ - def put_remove_Int(map: OpenHashMap[Int,Int], size: Int) { - val blocks = 50 // should be a factor of `size` - val totalPuts = 2 * size // add twice as many, because we remove half of them - val blockSize: Int = totalPuts / blocks + private def put_remove[K](map: OpenHashMap[K,Int], keys: KeySeq[K]) { + val blocks = 25 // should be a non-trivial factor of `size` + val size = keys.size + val blockSize: Int = size / blocks var base = 0 - while (base < totalPuts) { - put_Int(map, base + 1, base + blockSize) + while (base < size) { + put(map, keys, base, base + blockSize) // remove every other entry - var i = base + 1 - while (i <= base + blockSize) { - map.remove(i) + var i = base + while (i < base + blockSize) { + map.remove(keys(i)) i += 2 } @@ -150,55 +210,99 @@ private object OpenHashMapBenchmark { } /** Get elements from the given map. */ - def get_Int(map: OpenHashMap[Int,Int], size: Int, bh: Blackhole) { - var i = 1 - while (i <= size) { - bh.consume(map.get(i).getOrElse(0)) + private def get[K](map: OpenHashMap[K,Int], keys: KeySeq[K]) = { + val size = keys.size + var i = 0 + var sum = 0 + while (i < size) { + sum += map.get(keys(i)).getOrElse(0) i += 1 } + sum } } /** Benchmark for the library's [[OpenHashMap]]. */ @BenchmarkMode(Array(Mode.AverageTime)) -@Fork(6) +@Fork(5) @Threads(1) @Warmup(iterations = 20) -@Measurement(iterations = 6) +@Measurement(iterations = 5) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Benchmark) class OpenHashMapBenchmark { import OpenHashMapBenchmark._ - @Param(Array("25", "50", "100", "250", "1000", "2500", "10000", "25000", "100000", "250000", "1000000", "2500000", + @Param(Array("50", "100", "1000", "10000", "100000", "1000000", "2500000", "5000000", "7500000", "10000000", "25000000")) var size: Int = _ + // Tests with Int keys + /** Test putting elements to a map of `Int` to `Int`. */ @Benchmark - def put_Int(state: BulkPutState) { + def put_Int(state: IntBulkPutState) { var i = 0 while (i < state.maps.length) { - OpenHashMapBenchmark.put_Int(state.maps(i), 1, size) + put(state.maps(i), state.keys) i += 1 } } /** Test putting and removing elements to a growing map of `Int` to `Int`. */ @Benchmark - def put_remove_Int(state: BulkPutState) { + def put_remove_Int(state: IntBulkPutState) { var i = 0 while (i < state.maps.length) { - OpenHashMapBenchmark.put_remove_Int(state.maps(i), size) + put_remove(state.maps(i), state.keys) i += 1 } } /** Test getting elements from a map of `Int` to `Int`. */ @Benchmark - def put_get_Int(state: BulkGetState, bh: Blackhole) = OpenHashMapBenchmark.get_Int(state.map, size, bh) + def get_Int_after_put(state: IntBulkGetState) = + get(state.map, state.keys) + + /** Test getting elements from a map of `Int` to `Int` from which elements have been removed. + * Note that half of these queries will fail to find their keys, which have been removed. + */ + @Benchmark + def get_Int_after_put_remove(state: IntBulkRemovedGetState) = + get(state.map, state.keys) + + + // Tests with AnyRef keys + + /** Test putting elements to a map of `AnyRef` to `Int`. */ + @Benchmark + def put_AnyRef(state: AnyRefBulkPutState) { + var i = 0 + while (i < state.maps.length) { + put(state.maps(i), state.keys) + i += 1 + } + } + + /** Test putting and removing elements to a growing map of `AnyRef` to `Int`. */ + @Benchmark + def put_remove_AnyRef(state: AnyRefBulkPutState) { + var i = 0 + while (i < state.maps.length) { + put_remove(state.maps(i), state.keys) + i += 1 + } + } + + /** Test getting elements from a map of `AnyRef` to `Int`. */ + @Benchmark + def get_AnyRef_after_put(state: AnyRefBulkGetState) = + get(state.map, state.keys) - /** Test getting elements from a map of `Int` to `Int` from which elements have been removed. */ + /** Test getting elements from a map of `AnyRef` to `Int` from which elements have been removed. + * Note that half of these queries will fail to find their keys, which have been removed. + */ @Benchmark - def put_remove_get_Int(state: BulkRemovedGetState, bh: Blackhole) = OpenHashMapBenchmark.get_Int(state.map, size, bh) + def get_AnyRef_after_put_remove(state: AnyRefBulkRemovedGetState) = + get(state.map, state.keys) } diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala index 1a58b18ee979..b14b733a8128 100644 --- a/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/OpenHashMapRunner.scala @@ -1,20 +1,18 @@ package scala.collection.mutable -import java.io.BufferedWriter import java.io.File -import java.io.FileOutputStream -import java.io.OutputStreamWriter import java.io.PrintWriter -import scala.collection.JavaConversions + import scala.language.existentials + +import org.openjdk.jmh.results.Result import org.openjdk.jmh.results.RunResult import org.openjdk.jmh.runner.Runner import org.openjdk.jmh.runner.options.CommandLineOptions -import org.openjdk.jmh.runner.options.Options -import benchmark.JmhRunner import org.openjdk.jmh.runner.options.OptionsBuilder import org.openjdk.jmh.runner.options.VerboseMode -import org.openjdk.jmh.results.Result + +import benchmark.JmhRunner /** Replacement JMH application that runs the [[OpenHashMap]] benchmark. * @@ -27,6 +25,7 @@ object OpenHashMapRunner extends JmhRunner { /** Qualifier to add to the name of a memory usage data set. */ private[this] val memoryDatasetQualifier = "-memory" + /** Adapter to the JMH result class that simplifies our method calls. */ private[this] implicit class MyRunResult(r: RunResult) { /** Return the dataset label. */ def label = r.getPrimaryResult.getLabel @@ -34,13 +33,13 @@ object OpenHashMapRunner extends JmhRunner { /** Return the value of the JMH parameter for the number of map entries per invocation. */ def size: String = r.getParams.getParam("size") - /** Return the operation counts. */ + /** Return the operation counts. Not every test tracks this. */ def operations = Option(r.getSecondaryResults.get("operations")) /** Return the number of map entries. */ def entries = r.getSecondaryResults.get("mapEntries") - /** Return the memory usage. */ + /** Return the memory usage. Only defined if memory usage was measured. */ def memory = Option(r.getSecondaryResults.get("memory")) } @@ -50,7 +49,6 @@ object OpenHashMapRunner extends JmhRunner { def main(args: Array[String]) { import scala.collection.JavaConversions._ - import scala.language.existentials val opts = new CommandLineOptions(args: _*) var builder = new OptionsBuilder().parent(opts).jvmArgsPrepend("-Xmx6000m") @@ -58,7 +56,12 @@ object OpenHashMapRunner extends JmhRunner { val results = new Runner(builder.build).run() - // Sort the results + /* Sort the JMH results into "data sets", each representing a complete test of one feature. + * Some results only measure CPU performance; while others also measure memory usage, and + * thus are split into two data sets. A data set is distinguished by its label, which is + * the label of the JMH result, for CPU performance, or that with an added suffix, for memory + * usage. + */ /** Map from data set name to data set. */ val datasetByName = Map.empty[String, Set[RunResult]] @@ -83,23 +86,28 @@ object OpenHashMapRunner extends JmhRunner { val f = new PrintWriter(outputFile, "UTF-8") try { - datasetByName.foreach(_ match { case (label: String, dataset: Iterable[RunResult]) => { - f.println(s"# [$label]") - - val isMemoryUsageDataset = label.endsWith(memoryDatasetQualifier) - dataset.foreach { r => - f.println(r.size + " " + ( - if (isMemoryUsageDataset) - stats(r.entries) + " " + stats(r.memory.get) - else - stats(r.operations getOrElse r.getPrimaryResult) - )) - } - - f.println(); f.println() // data set separator - }}) + datasetByName.foreach(_ match { + case (label: String, dataset: Iterable[RunResult]) => + outputDataset(f, label, dataset) + }) } finally { f.close() } } + + private[this] def outputDataset(f: PrintWriter, label: String, dataset: Iterable[RunResult]) { + f.println(s"# [$label]") + + val isMemoryUsageDataset = label.endsWith(memoryDatasetQualifier) + dataset.foreach { r => + f.println(r.size + " " + ( + if (isMemoryUsageDataset && !r.memory.get.getScore.isInfinite) + stats(r.entries) + " " + stats(r.memory.get) + else + stats(r.operations getOrElse r.getPrimaryResult) + )) + } + + f.println(); f.println() // data set separator + } } From fd6386a51e9a5b97a83198a310923cd012e1aab0 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 26 May 2016 21:53:19 -0700 Subject: [PATCH 067/153] SI-9794 Error advice uses decoded method name So much work went into polishing this error message, it's worth buffing the method name when it's an operator. The message now says `+` instead of `$plus`. --- .../scala/tools/nsc/typechecker/ContextErrors.scala | 2 +- test/files/neg/missing-arg-list.check | 7 ++++++- test/files/neg/missing-arg-list.scala | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 90ccaefe432a..d519948a11f0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -632,7 +632,7 @@ trait ContextErrors { //adapt def MissingArgsForMethodTpeError(tree: Tree, meth: Symbol) = { - val f = meth.name + val f = meth.name.decoded val paf = s"$f(${ meth.asMethod.paramLists map (_ map (_ => "_") mkString ",") mkString ")(" })" val advice = s""" |Unapplied methods are only converted to functions when a function type is expected. diff --git a/test/files/neg/missing-arg-list.check b/test/files/neg/missing-arg-list.check index 5a011c36f29b..229baac177ea 100644 --- a/test/files/neg/missing-arg-list.check +++ b/test/files/neg/missing-arg-list.check @@ -18,4 +18,9 @@ Unapplied methods are only converted to functions when a function type is expect You can make this conversion explicit by writing `h _` or `h(_,_,_)(_)` instead of `h`. val z = h ^ -four errors found +missing-arg-list.scala:15: error: missing argument list for method + in trait T +Unapplied methods are only converted to functions when a function type is expected. +You can make this conversion explicit by writing `+ _` or `+(_)` instead of `+`. + val p = + + ^ +5 errors found diff --git a/test/files/neg/missing-arg-list.scala b/test/files/neg/missing-arg-list.scala index c422dd32fe6a..44b83e429d31 100644 --- a/test/files/neg/missing-arg-list.scala +++ b/test/files/neg/missing-arg-list.scala @@ -10,4 +10,7 @@ trait T { val x = f val y = g val z = h + + def +(i: Int) = i + 42 + val p = + } From 6e9faf5157132ad575c98e5a9a0919ac38b7beb8 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Wed, 27 Apr 2016 21:25:57 +0200 Subject: [PATCH 068/153] Right-bias Either - Add operations like map, flatMap which assume right-bias - Deprecate {Left,Right}Projection - Deprecate left and right in favor of swap - Add contains, toOption, toTry, toSeq and filterOrElse - toSeq returns collection.immutable.Seq instead of collection.Seq - Don't add get There are no incompatible changes. The only possibility of breakage that exists is when people have added extension methods named map, flatMap etc. to Either in the past doing something different than the methods added to Either now. One detail that moved the scales in favor of deprecating LeftProjection and RightProjection was the desire to have toSeq return scala.collection.immutable.Seq instead of scala.collection.Seq like LeftProjection and RightProjection do. Therefore keeping LeftProjection and RightProjection would introduce inconsistency. filter is called filterOrElse because filtering in a for-comprehension doesn't work if the method needs an explicit argument. contains was added as safer alternative to if (either.isRight && either.right.get == $something) ... While adding filter with an implicit zero value is possible, it's dangerous as it would require that developers add a "naked" implicit value of type A to their scope and it would close the door to a future in which the Scala standard library ships with Monoid and filter could exist with an implicit Monoid parameter. --- .../nsc/backend/jvm/BackendReporting.scala | 13 +- src/library/scala/util/Either.scala | 312 +++++++++++++----- test/files/presentation/doc/doc.scala | 6 +- test/files/presentation/t7678/Runner.scala | 2 +- test/files/scalacheck/CheckEither.scala | 70 +++- 5 files changed, 309 insertions(+), 94 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala index 4287c24dc806..fd558587e9e0 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala @@ -26,9 +26,7 @@ final class BackendReportingImpl(val global: Global) extends BackendReporting { /** * Utilities for error reporting. * - * Defines some tools to make error reporting with Either easier. Would be subsumed by a right-biased - * Either in the standard library (or scalaz \/) (Validation is different, it accumulates multiple - * errors). + * Defines some utility methods to make error reporting with Either easier. */ object BackendReporting { def methodSignature(classInternalName: InternalName, name: String, desc: String) = { @@ -42,19 +40,12 @@ object BackendReporting { def assertionError(message: String): Nothing = throw new AssertionError(message) implicit class RightBiasedEither[A, B](val v: Either[A, B]) extends AnyVal { - def map[C](f: B => C): Either[A, C] = v.right.map(f) - def flatMap[C](f: B => Either[A, C]): Either[A, C] = v.right.flatMap(f) def withFilter(f: B => Boolean)(implicit empty: A): Either[A, B] = v match { case Left(_) => v case Right(e) => if (f(e)) v else Left(empty) // scalaz.\/ requires an implicit Monoid m to get m.empty } - def foreach[U](f: B => U): Unit = v.right.foreach(f) - def getOrElse[C >: B](alt: => C): C = v.right.getOrElse(alt) - - /** - * Get the value, fail with an assertion if this is an error. - */ + /** Get the value, fail with an assertion if this is an error. */ def get: B = { assert(v.isRight, v.left.get) v.right.get diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index 01da0c1ef2bd..6da39692c51b 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -32,12 +32,21 @@ package util * Left(in) * } * - * println( result match { - * case Right(x) => "You passed me the Int: " + x + ", which I will increment. " + x + " + 1 = " + (x+1) - * case Left(x) => "You passed me the String: " + x + * println(result match { + * case Right(x) => s"You passed me the Int: $x, which I will increment. $x + 1 = ${x+1}" + * case Left(x) => s"You passed me the String: $x" * }) * }}} * + * Either is right-biased, which means that Right is assumed to be the default case to + * operate on. If it is Left, operations like map, flatMap, ... return the Left value + * unchanged: + * + * {{{ + * Right(12).map(_ * 2) // Right(24) + * Left(23).map(_ * 2) // Left(23) + * }}} + * * A ''projection'' can be used to selectively operate on a value of type Either, * depending on whether it is of type Left or Right. For example, to transform an * Either using a function, in the case where it's a Left, one can first apply @@ -70,11 +79,13 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { /** * Projects this `Either` as a `Left`. */ + @deprecated("use swap instead", "2.12.0") def left = Either.LeftProjection(this) /** * Projects this `Either` as a `Right`. */ + @deprecated("Either is now right-biased", "2.12.0") def right = Either.RightProjection(this) /** @@ -83,8 +94,8 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * @example {{{ * val result: Either[Exception, Value] = possiblyFailingOperation() * log(result.fold( - * ex => "Operation failed with " + ex, - * v => "Operation produced value: " + v + * ex => s"Operation failed with $ex", + * v => s"Operation produced value: $v" * )) * }}} * @@ -92,9 +103,9 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * @param fb the function to apply if this is a `Right` * @return the results of applying the function */ - def fold[X](fa: A => X, fb: B => X) = this match { - case Left(a) => fa(a) + def fold[C](fa: A => C, fb: B => C): C = this match { case Right(b) => fb(b) + case Left(a) => fa(a) } /** @@ -105,8 +116,8 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * val r: Either[Int, String] = l.swap // Result: Right("left") * }}} */ - def swap = this match { - case Left(a) => Right(a) + def swap: Either[B, A] = this match { + case Left(a) => Right(a) case Right(b) => Left(b) } @@ -130,8 +141,9 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * This method, and `joinLeft`, are analogous to `Option#flatten` */ def joinRight[A1 >: A, B1 >: B, C](implicit ev: B1 <:< Either[A1, C]): Either[A1, C] = this match { - case Left(a) => Left(a) case Right(b) => b + case Left(a) => this.asInstanceOf[Either[A1, C]] + } /** @@ -155,7 +167,155 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { */ def joinLeft[A1 >: A, B1 >: B, C](implicit ev: A1 <:< Either[C, B1]): Either[C, B1] = this match { case Left(a) => a - case Right(b) => Right(b) + case Right(b) => this.asInstanceOf[Either[C, B1]] + } + + /** + * Executes the given side-effecting function if this is a `Right`. + * + * {{{ + * Right(12).foreach(x => println(x)) // prints "12" + * Left(12).foreach(x => println(x)) // doesn't print + * }}} + * @param f The side-effecting function to execute. + */ + def foreach[U](f: B => U): Unit = this match { + case Right(b) => f(b) + case Left(_) => + } + + /** + * Returns the value from this `Right` or the given argument if this is a `Left`. + * + * {{{ + * Right(12).getOrElse(17) // 12 + * Left(12).getOrElse(17) // 17 + * }}} + */ + def getOrElse[BB >: B](or: => BB): BB = this match { + case Right(b) => b + case Left(_) => or + } + + /** Returns `true` if this is a `Right` and its value is equal to `elem` (as determined by `==`), + * returns `false` otherwise. + * + * {{{ + * // Returns true because value of Right is "something" which equals "something". + * Right("something") contains "something" + * + * // Returns false because value of Right is "something" which does not equal "anything". + * Right("something") contains "anything" + * + * // Returns false because there is no value for Right. + * Left("something") contains "something" + * }}} + * + * @param elem the element to test. + * @return `true` if the option has an element that is equal (as determined by `==`) to `elem`, `false` otherwise. + */ + final def contains[AA >: A](elem: AA): Boolean = this match { + case Right(b) => b == elem + case Left(_) => false + } + + /** + * Returns `true` if `Left` or returns the result of the application of + * the given function to the `Right` value. + * + * {{{ + * Right(12).forall(_ > 10) // true + * Right(7).forall(_ > 10) // false + * Left(12).forall(_ > 10) // true + * }}} + */ + def forall(f: B => Boolean): Boolean = this match { + case Right(b) => f(b) + case Left(_) => true + } + + /** + * Returns `false` if `Left` or returns the result of the application of + * the given function to the `Right` value. + * + * {{{ + * Right(12).exists(_ > 10) // true + * Right(7).exists(_ > 10) // false + * Left(12).exists(_ > 10) // false + * }}} + */ + def exists(p: B => Boolean): Boolean = this match { + case Right(b) => p(b) + case Left(_) => false + } + + /** + * Binds the given function across `Right`. + * + * @param f The function to bind across `Right`. + */ + def flatMap[AA >: A, Y](f: B => Either[AA, Y]): Either[AA, Y] = this match { + case Right(b) => f(b) + case Left(a) => this.asInstanceOf[Either[AA, Y]] + } + + /** + * The given function is applied if this is a `Right`. + * + * {{{ + * Right(12).map(x => "flower") // Result: Right("flower") + * Left(12).map(x => "flower") // Result: Left(12) + * }}} + */ + def map[Y](f: B => Y): Either[A, Y] = this match { + case Right(b) => Right(f(b)) + case Left(a) => this.asInstanceOf[Either[A, Y]] + } + + /** Returns `Right` with the existing value of `Right` if this is a `Right` and the given predicate `p` holds for the right value, + * returns `Left(zero)` if this is a `Right` and the given predicate `p` does not hold for the right value, + * returns `Left` with the existing value of `Left` if this is a `Left`. + * + * {{{ + * Right(12).filterOrElse(_ > 10, -1) // Right(12) + * Right(7).filterOrElse(_ > 10, -1) // Left(-1) + * Left(12).filterOrElse(_ > 10, -1) // Left(12) + * }}} + */ + def filterOrElse[AA >: A](p: B => Boolean, zero: => AA): Either[AA, B] = this match { + case Right(b) => if (p(b)) this else Left(zero) + case Left(a) => this + } + + /** Returns a `Seq` containing the `Right` value if + * it exists or an empty `Seq` if this is a `Left`. + * + * {{{ + * Right(12).toSeq // Seq(12) + * Left(12).toSeq // Seq() + * }}} + */ + def toSeq: collection.immutable.Seq[B] = this match { + case Right(b) => collection.immutable.Seq(b) + case Left(_) => collection.immutable.Seq.empty + } + + /** Returns a `Some` containing the `Right` value + * if it exists or a `None` if this is a `Left`. + * + * {{{ + * Right(12).toOption // Some(12) + * Left(12).toOption // None + * }}} + */ + def toOption: Option[B] = this match { + case Right(b) => Some(b) + case Left(_) => None + } + + def toTry(implicit ev: A <:< Throwable): Try[B] = this match { + case Right(b) => Success(b) + case Left(a) => Failure(a) } /** @@ -186,7 +346,7 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * @version 1.0, 11/10/2008 */ final case class Left[+A, +B](a: A) extends Either[A, B] { - def isLeft = true + def isLeft = true def isRight = false } @@ -197,12 +357,26 @@ final case class Left[+A, +B](a: A) extends Either[A, B] { * @version 1.0, 11/10/2008 */ final case class Right[+A, +B](b: B) extends Either[A, B] { - def isLeft = false + def isLeft = false def isRight = true } object Either { + /** If the condition is satisfied, return the given `B` in `Right`, + * otherwise, return the given `A` in `Left`. + * + * {{{ + * val userInput: String = ... + * Either.cond( + * userInput.forall(_.isDigit) && userInput.size == 10, + * PhoneNumber(userInput), + * "The input (%s) does not look like a phone number".format(userInput) + * }}} + */ + def cond[X, Y](test: Boolean, right: => Y, left: => X): Either[X, Y] = + if (test) Right(right) else Left(left) + /** * Allows use of a `merge` method to extract values from Either instances * regardless of whether they are Left or Right. @@ -216,8 +390,8 @@ object Either { */ implicit class MergeableEither[A](private val x: Either[A, A]) extends AnyVal { def merge: A = x match { - case Left(a) => a case Right(a) => a + case Left(a) => a } } @@ -250,7 +424,7 @@ object Either { * }}} * * {{{ - * // using Either + * // using Either * def interactWithDB(x: Query): Either[Exception, Result] = * try { * Right(getResultFromDatabase(x)) @@ -270,6 +444,7 @@ object Either { * @author Tony Morris, Workingmouse * @version 1.0, 11/10/2008 */ + @deprecated("use swap instead", "2.12.0") final case class LeftProjection[+A, +B](e: Either[A, B]) { /** * Returns the value from this `Left` or throws `java.util.NoSuchElementException` @@ -282,9 +457,9 @@ object Either { * * @throws java.util.NoSuchElementException if the projection is [[scala.util.Right]] */ - def get = e match { - case Left(a) => a - case Right(_) => throw new NoSuchElementException("Either.left.value on Right") + def get: A = e match { + case Left(a) => a + case Right(_) => throw new NoSuchElementException("Either.left.get on Right") } /** @@ -296,14 +471,13 @@ object Either { * }}} * @param f The side-effecting function to execute. */ - def foreach[U](f: A => U) = e match { - case Left(a) => f(a) - case Right(_) => {} + def foreach[U](f: A => U): Unit = e match { + case Left(a) => f(a) + case Right(_) => } /** - * Returns the value from this `Left` or the given argument if this is a - * `Right`. + * Returns the value from this `Left` or the given argument if this is a `Right`. * * {{{ * Left(12).left.getOrElse(17) // 12 @@ -311,8 +485,8 @@ object Either { * }}} * */ - def getOrElse[AA >: A](or: => AA) = e match { - case Left(a) => a + def getOrElse[AA >: A](or: => AA): AA = e match { + case Left(a) => a case Right(_) => or } @@ -327,8 +501,8 @@ object Either { * }}} * */ - def forall(@deprecatedName('f) p: A => Boolean) = e match { - case Left(a) => p(a) + def forall(@deprecatedName('f) p: A => Boolean): Boolean = e match { + case Left(a) => p(a) case Right(_) => true } @@ -343,8 +517,8 @@ object Either { * }}} * */ - def exists(@deprecatedName('f) p: A => Boolean) = e match { - case Left(a) => p(a) + def exists(@deprecatedName('f) p: A => Boolean): Boolean = e match { + case Left(a) => p(a) case Right(_) => false } @@ -357,9 +531,9 @@ object Either { * }}} * @param f The function to bind across `Left`. */ - def flatMap[BB >: B, X](f: A => Either[X, BB]) = e match { - case Left(a) => f(a) - case Right(b) => Right(b) + def flatMap[BB >: B, X](f: A => Either[X, BB]): Either[X, BB] = e match { + case Left(a) => f(a) + case Right(b) => e.asInstanceOf[Either[X, BB]] } /** @@ -370,9 +544,9 @@ object Either { * Right[Int, Int](12).left.map(_ + 2) // Right(12) * }}} */ - def map[X](f: A => X) = e match { - case Left(a) => Left(f(a)) - case Right(b) => Right(b) + def map[X](f: A => X): Either[X, B] = e match { + case Left(a) => Left(f(a)) + case Right(b) => e.asInstanceOf[Either[X, B]] } /** @@ -386,7 +560,7 @@ object Either { * }}} */ def filter[Y](p: A => Boolean): Option[Either[A, Y]] = e match { - case Left(a) => if(p(a)) Some(Left(a)) else None + case Left(a) => if(p(a)) Some(Left(a)) else None case Right(b) => None } @@ -399,8 +573,8 @@ object Either { * Right(12).left.toSeq // Seq() * }}} */ - def toSeq = e match { - case Left(a) => Seq(a) + def toSeq: Seq[A] = e match { + case Left(a) => Seq(a) case Right(_) => Seq.empty } @@ -413,8 +587,8 @@ object Either { * Right(12).left.toOption // None * }}} */ - def toOption = e match { - case Left(a) => Some(a) + def toOption: Option[A] = e match { + case Left(a) => Some(a) case Right(_) => None } } @@ -434,6 +608,7 @@ object Either { * @author Tony Morris, Workingmouse * @version 1.0, 11/10/2008 */ + @deprecated("Either is now right-biased", "2.12.0") final case class RightProjection[+A, +B](e: Either[A, B]) { /** @@ -447,9 +622,9 @@ object Either { * * @throws java.util.NoSuchElementException if the projection is `Left`. */ - def get = e match { - case Left(_) => throw new NoSuchElementException("Either.right.value on Left") - case Right(a) => a + def get: B = e match { + case Right(b) => b + case Left(_) => throw new NoSuchElementException("Either.right.get on Left") } /** @@ -461,23 +636,22 @@ object Either { * }}} * @param f The side-effecting function to execute. */ - def foreach[U](f: B => U) = e match { - case Left(_) => {} + def foreach[U](f: B => U): Unit = e match { case Right(b) => f(b) + case Left(_) => } /** - * Returns the value from this `Right` or the given argument if this is a - * `Left`. + * Returns the value from this `Right` or the given argument if this is a `Left`. * * {{{ * Right(12).right.getOrElse(17) // 12 * Left(12).right.getOrElse(17) // 17 * }}} */ - def getOrElse[BB >: B](or: => BB) = e match { - case Left(_) => or + def getOrElse[BB >: B](or: => BB): BB = e match { case Right(b) => b + case Left(_) => or } /** @@ -490,9 +664,9 @@ object Either { * Left(12).right.forall(_ > 10) // true * }}} */ - def forall(f: B => Boolean) = e match { - case Left(_) => true + def forall(f: B => Boolean): Boolean = e match { case Right(b) => f(b) + case Left(_) => true } /** @@ -505,9 +679,9 @@ object Either { * Left(12).right.exists(_ > 10) // false * }}} */ - def exists(@deprecatedName('f) p: B => Boolean) = e match { - case Left(_) => false + def exists(@deprecatedName('f) p: B => Boolean): Boolean = e match { case Right(b) => p(b) + case Left(_) => false } /** @@ -515,9 +689,9 @@ object Either { * * @param f The function to bind across `Right`. */ - def flatMap[AA >: A, Y](f: B => Either[AA, Y]) = e match { - case Left(a) => Left(a) + def flatMap[AA >: A, Y](f: B => Either[AA, Y]): Either[AA, Y] = e match { case Right(b) => f(b) + case Left(a) => e.asInstanceOf[Either[AA, Y]] } /** @@ -528,9 +702,9 @@ object Either { * Left(12).right.map(x => "flower") // Result: Left(12) * }}} */ - def map[Y](f: B => Y) = e match { - case Left(a) => Left(a) + def map[Y](f: B => Y): Either[A, Y] = e match { case Right(b) => Right(f(b)) + case Left(a) => e.asInstanceOf[Either[A, Y]] } /** Returns `None` if this is a `Left` or if the @@ -544,8 +718,8 @@ object Either { * }}} */ def filter[X](p: B => Boolean): Option[Either[X, B]] = e match { - case Left(_) => None case Right(b) => if(p(b)) Some(Right(b)) else None + case Left(_) => None } /** Returns a `Seq` containing the `Right` value if @@ -556,9 +730,9 @@ object Either { * Left(12).right.toSeq // Seq() * }}} */ - def toSeq = e match { - case Left(_) => Seq.empty + def toSeq: Seq[B] = e match { case Right(b) => Seq(b) + case Left(_) => Seq.empty } /** Returns a `Some` containing the `Right` value @@ -569,23 +743,9 @@ object Either { * Left(12).right.toOption // None * }}} */ - def toOption = e match { - case Left(_) => None + def toOption: Option[B] = e match { case Right(b) => Some(b) + case Left(_) => None } } - - /** If the condition is satisfied, return the given `B` in `Right`, - * otherwise, return the given `A` in `Left`. - * - * {{{ - * val userInput: String = ... - * Either.cond( - * userInput.forall(_.isDigit) && userInput.size == 10, - * PhoneNumber(userInput), - * "The input (%s) does not look like a phone number".format(userInput) - * }}} - */ - def cond[A, B](test: Boolean, right: => B, left: => A): Either[A, B] = - if (test) Right(right) else Left(left) } diff --git a/test/files/presentation/doc/doc.scala b/test/files/presentation/doc/doc.scala index ce431910ee94..8c60af557b96 100644 --- a/test/files/presentation/doc/doc.scala +++ b/test/files/presentation/doc/doc.scala @@ -62,7 +62,7 @@ object Test extends InteractiveTest { def getComment(sym: Symbol, source: SourceFile, fragments: List[(Symbol,SourceFile)]): Option[Comment] = { val docResponse = new Response[(String, String, Position)] askDocComment(sym, source, sym.owner, fragments, docResponse) - docResponse.get.left.toOption flatMap { + docResponse.get.swap.toOption flatMap { case (expanded, raw, pos) => if (expanded.isEmpty) None @@ -85,13 +85,13 @@ object Test extends InteractiveTest { val batch = new BatchSourceFile(source.file, newText.toCharArray) val reloadResponse = new Response[Unit] compiler.askReload(List(batch), reloadResponse) - reloadResponse.get.left.toOption match { + reloadResponse.get.swap.toOption match { case None => println("Couldn't reload") case Some(_) => val parseResponse = new Response[Tree] askParsedEntered(batch, true, parseResponse) - parseResponse.get.left.toOption match { + parseResponse.get.swap.toOption match { case None => println("Couldn't parse") case Some(_) => diff --git a/test/files/presentation/t7678/Runner.scala b/test/files/presentation/t7678/Runner.scala index 14d6dc2a7051..c6736a65b020 100644 --- a/test/files/presentation/t7678/Runner.scala +++ b/test/files/presentation/t7678/Runner.scala @@ -7,7 +7,7 @@ object Test extends InteractiveTest { override def runDefaultTests() { def resolveTypeTagHyperlink() { - val sym = compiler.askForResponse(() => compiler.currentRun.runDefinitions.TypeTagClass).get.left.get + val sym = compiler.askForResponse(() => compiler.currentRun.runDefinitions.TypeTagClass).get.swap.getOrElse(???) val r = new Response[Position] compiler.askLinkPos(sym, new BatchSourceFile("", source), r) r.get diff --git a/test/files/scalacheck/CheckEither.scala b/test/files/scalacheck/CheckEither.scala index 48f732a22d6e..f0ec79704544 100644 --- a/test/files/scalacheck/CheckEither.scala +++ b/test/files/scalacheck/CheckEither.scala @@ -132,6 +132,58 @@ object Test extends Properties("Either") { case Right(a) => a })) + val prop_getOrElse = forAll((e: Either[Int, Int], or: Int) => e.getOrElse(or) == (e match { + case Left(_) => or + case Right(b) => b + })) + + val prop_contains = forAll((e: Either[Int, Int], n: Int) => + e.contains(n) == (e.isRight && e.right.get == n)) + + val prop_forall = forAll((e: Either[Int, Int]) => + e.forall(_ % 2 == 0) == (e.isLeft || e.right.get % 2 == 0)) + + val prop_exists = forAll((e: Either[Int, Int]) => + e.exists(_ % 2 == 0) == (e.isRight && e.right.get % 2 == 0)) + + val prop_flatMapLeftIdentity = forAll((e: Either[Int, Int], n: Int, s: String) => { + def f(x: Int) = if(x % 2 == 0) Left(s) else Right(s) + Right(n).flatMap(f(_)) == f(n)}) + + val prop_flatMapRightIdentity = forAll((e: Either[Int, Int]) => e.flatMap(Right(_)) == e) + + val prop_flatMapComposition = forAll((e: Either[Int, Int]) => { + def f(x: Int) = if(x % 2 == 0) Left(x) else Right(x) + def g(x: Int) = if(x % 7 == 0) Right(x) else Left(x) + e.flatMap(f(_)).flatMap(g(_)) == e.flatMap(f(_).flatMap(g(_)))}) + + val prop_mapIdentity = forAll((e: Either[Int, Int]) => e.map(x => x) == e) + + val prop_mapComposition = forAll((e: Either[Int, String]) => { + def f(s: String) = s.toLowerCase + def g(s: String) = s.reverse + e.map(x => f(g(x))) == e.map(x => g(x)).map(f(_))}) + + val prop_filterOrElse = forAll((e: Either[Int, Int], x: Int) => e.filterOrElse(_ % 2 == 0, -x) == + (if(e.isLeft) e + else if(e.right.get % 2 == 0) e + else Left(-x))) + + val prop_seq = forAll((e: Either[Int, Int]) => e.toSeq == (e match { + case Left(_) => collection.immutable.Seq.empty + case Right(b) => collection.immutable.Seq(b) + })) + + val prop_option = forAll((e: Either[Int, Int]) => e.toOption == (e match { + case Left(_) => None + case Right(b) => Some(b) + })) + + val prop_try = forAll((e: Either[Throwable, Int]) => e.toTry == (e match { + case Left(a) => util.Failure(a) + case Right(b) => util.Success(b) + })) + /** Hard to believe I'm "fixing" a test to reflect B before A ... */ val prop_Either_cond = forAll((c: Boolean, a: Int, b: Int) => Either.cond(c, a, b) == (if(c) Right(a) else Left(b))) @@ -169,9 +221,21 @@ object Test extends Properties("Either") { ("prop_Either_right", prop_Either_right), ("prop_Either_joinLeft", prop_Either_joinLeft), ("prop_Either_joinRight", prop_Either_joinRight), - ("prop_Either_reduce", prop_Either_reduce), - ("prop_Either_cond", prop_Either_cond) - ) + ("prop_Either_reduce", prop_Either_reduce), + ("prop_getOrElse", prop_getOrElse), + ("prop_contains", prop_contains), + ("prop_forall", prop_forall), + ("prop_exists", prop_exists), + ("prop_flatMapLeftIdentity", prop_flatMapLeftIdentity), + ("prop_flatMapRightIdentity", prop_flatMapRightIdentity), + ("prop_flatMapComposition", prop_flatMapComposition), + ("prop_mapIdentity", prop_mapIdentity), + ("prop_mapComposition", prop_mapComposition), + ("prop_filterOrElse", prop_filterOrElse), + ("prop_seq", prop_seq), + ("prop_option", prop_option), + ("prop_try", prop_try), + ("prop_Either_cond", prop_Either_cond)) for ((label, prop) <- tests) { property(label) = prop From 981e3c51d5040ea808b5f699718db55241ee42cf Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Sat, 2 Apr 2016 12:40:25 +0200 Subject: [PATCH 069/153] SI-9483 Add `since` to `@deprecatedName` --- src/library/scala/deprecatedName.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/library/scala/deprecatedName.scala b/src/library/scala/deprecatedName.scala index a0d3aa829b28..da8b76efc90f 100644 --- a/src/library/scala/deprecatedName.scala +++ b/src/library/scala/deprecatedName.scala @@ -29,6 +29,4 @@ import scala.annotation.meta._ * @since 2.8.1 */ @param -class deprecatedName(name: Symbol) extends scala.annotation.StaticAnnotation { - def this() = this(Symbol("")) -} +class deprecatedName(name: Symbol = Symbol(""), since: String = "") extends scala.annotation.StaticAnnotation From 673350e08af72454fe9df87ae7f3292893e44d3c Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Sat, 2 Apr 2016 13:38:15 +0200 Subject: [PATCH 070/153] SI-9084 Add `since` (if available) to deprecation warnings --- src/compiler/scala/tools/nsc/Reporting.scala | 5 ++-- .../tools/nsc/typechecker/Adaptations.scala | 2 +- .../tools/nsc/typechecker/NamesDefaults.scala | 5 ++-- .../tools/nsc/typechecker/RefChecks.scala | 7 +++-- .../scala/tools/nsc/typechecker/Typers.scala | 7 +++-- .../scala/collection/convert/package.scala | 12 ++++---- .../scala/reflect/internal/Symbols.scala | 27 ++++++++++-------- test/files/jvm/t8582.check | 2 +- test/files/neg/beanInfoDeprecation.check | 2 +- .../neg/classmanifests_new_deprecations.check | 16 +++++------ test/files/neg/delayed-init-ref.check | 2 +- test/files/neg/names-defaults-neg-warn.check | 4 +-- test/files/neg/names-defaults-neg.check | 6 ++-- test/files/neg/t4851.check | 8 +++--- test/files/neg/t6120.check | 4 +-- test/files/neg/t6162-inheritance.check | 2 +- test/files/neg/t6162-overriding.check | 2 +- test/files/neg/t6406-regextract.check | 2 +- test/files/neg/t7294b.check | 2 +- test/files/neg/t7783.check | 10 +++---- test/files/neg/t8035-deprecated.check | 6 ++-- test/files/neg/t8685.check | 28 +++++++++---------- test/files/neg/t9684.check | 4 +-- test/files/run/t3235-minimal.check | 8 +++--- test/files/run/t4542.check | 2 +- test/files/run/t4594-repl-settings.scala | 2 +- test/files/run/toolbox_console_reporter.check | 4 +-- test/files/run/toolbox_silent_reporter.check | 2 +- 28 files changed, 96 insertions(+), 87 deletions(-) diff --git a/src/compiler/scala/tools/nsc/Reporting.scala b/src/compiler/scala/tools/nsc/Reporting.scala index 8d0aedc76db8..325537a5a8d9 100644 --- a/src/compiler/scala/tools/nsc/Reporting.scala +++ b/src/compiler/scala/tools/nsc/Reporting.scala @@ -68,8 +68,9 @@ trait Reporting extends scala.reflect.internal.Reporting { self: ast.Positions w // behold! the symbol that caused the deprecation warning (may not be deprecated itself) def deprecationWarning(pos: Position, sym: Symbol, msg: String): Unit = _deprecationWarnings.warn(pos, msg) def deprecationWarning(pos: Position, sym: Symbol): Unit = { - val suffix = sym.deprecationMessage match { case Some(msg) => ": "+ msg case _ => "" } - deprecationWarning(pos, sym, s"$sym${sym.locationString} is deprecated$suffix") + val version = sym.deprecationVersion match { case Some(ver) => s" (since $ver)" case _ => "" } + val message = sym.deprecationMessage match { case Some(msg) => s": $msg" case _ => "" } + deprecationWarning(pos, sym, s"$sym${sym.locationString} is deprecated$version$message") } private[this] var reportedFeature = Set[Symbol]() diff --git a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala index 2f4d2283476a..46561de78f13 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala @@ -74,7 +74,7 @@ trait Adaptations { if (settings.future) context.error(t.pos, adaptWarningMessage("Adaptation of argument list by inserting () has been removed.", showAdaptation = false)) else { - val msg = "Adaptation of argument list by inserting () has been deprecated: " + ( + val msg = "Adaptation of argument list by inserting () is deprecated: " + ( if (isLeakyTarget) "leaky (Object-receiving) target makes this especially dangerous." else "this is unlikely to be what you want.") context.deprecationWarning(t.pos, t.symbol, adaptWarningMessage(msg)) diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 5062289ed1f3..063cfd38054e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -565,14 +565,15 @@ trait NamesDefaults { self: Analyzer => case Some(`name`) => true case Some(nme.NO_NAME) => anonOK } + def since = param.deprecatedParamVersion.map(ver => s" (since $ver)").getOrElse("") def checkName = { val res = param.name == name - if (res && checkDeprecation(true)) warn(s"naming parameter $name has been deprecated.") + if (res && checkDeprecation(true)) warn(s"naming parameter $name is deprecated$since.") res } def checkAltName = { val res = checkDeprecation(false) - if (res) warn(s"the parameter name $name has been deprecated. Use ${param.name} instead.") + if (res) warn(s"the parameter name $name is deprecated$since: Use ${param.name} instead") res } !param.isSynthetic && (checkName || checkAltName) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index da269168ec61..3aea64a1f277 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -548,9 +548,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def checkOverrideDeprecated() { if (other.hasDeprecatedOverridingAnnotation && !member.ownerChain.exists(x => x.isDeprecated || x.hasBridgeAnnotation)) { - val suffix = other.deprecatedOverridingMessage map (": " + _) getOrElse "" - val msg = s"overriding ${other.fullLocationString} is deprecated$suffix" - currentRun.reporting.deprecationWarning(member.pos, other, msg) + val version = other.deprecatedOverridingVersion map (ver => s" (since $ver)") getOrElse "" + val message = other.deprecatedOverridingMessage map (msg => s": $msg") getOrElse "" + val report = s"overriding ${other.fullLocationString} is deprecated$version$message" + currentRun.reporting.deprecationWarning(member.pos, other, report) } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1aed9c3a64cf..d44a0eaf59fd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1704,9 +1704,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (!isPastTyper && psym.hasDeprecatedInheritanceAnnotation && !sameSourceFile && !context.owner.ownerChain.exists(x => x.isDeprecated || x.hasBridgeAnnotation)) { - val suffix = psym.deprecatedInheritanceMessage map (": " + _) getOrElse "" - val msg = s"inheritance from ${psym.fullLocationString} is deprecated$suffix" - context.deprecationWarning(parent.pos, psym, msg) + val version = psym.deprecatedInheritanceVersion map (ver => s" (since $ver)") getOrElse "" + val message = psym.deprecatedInheritanceMessage map (msg => s": $msg") getOrElse "" + val report = s"inheritance from ${psym.fullLocationString} is deprecated$version$message" + context.deprecationWarning(parent.pos, psym, report) } if (psym.isSealed && !phase.erasedTypes) diff --git a/src/library/scala/collection/convert/package.scala b/src/library/scala/collection/convert/package.scala index 7f48023b58b6..fe1951b6cf70 100644 --- a/src/library/scala/collection/convert/package.scala +++ b/src/library/scala/collection/convert/package.scala @@ -10,17 +10,17 @@ package scala package collection package object convert { - @deprecated("Use JavaConverters", since="2.12") + @deprecated("use JavaConverters", since="2.12") val decorateAsJava = new DecorateAsJava { } - @deprecated("Use JavaConverters", since="2.12") + @deprecated("use JavaConverters", since="2.12") val decorateAsScala = new DecorateAsScala { } - @deprecated("Use JavaConverters", since="2.12") + @deprecated("use JavaConverters", since="2.12") val decorateAll = JavaConverters - @deprecated("Use JavaConverters or consider ImplicitConversionsToJava", since="2.12") + @deprecated("use JavaConverters or consider ImplicitConversionsToJava", since="2.12") val wrapAsJava = new WrapAsJava { } - @deprecated("Use JavaConverters or consider ImplicitConversionsToScala", since="2.12") + @deprecated("use JavaConverters or consider ImplicitConversionsToScala", since="2.12") val wrapAsScala = new WrapAsScala { } - @deprecated("Use JavaConverters or consider ImplicitConversions", since="2.12") + @deprecated("use JavaConverters or consider ImplicitConversions", since="2.12") val wrapAll = new WrapAsJava with WrapAsScala { } } diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index ed514143822d..8f24b435b3c1 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -871,21 +871,26 @@ trait Symbols extends api.Symbols { self: SymbolTable => ) } - def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr) - def isSerializable = info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass) - def hasBridgeAnnotation = hasAnnotation(BridgeClass) - def isDeprecated = hasAnnotation(DeprecatedAttr) - def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0) - def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1) - def deprecatedParamName = getAnnotation(DeprecatedNameAttr) flatMap (_ symbolArg 0 orElse Some(nme.NO_NAME)) + def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr) + def isSerializable = info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass) + def hasBridgeAnnotation = hasAnnotation(BridgeClass) + def isDeprecated = hasAnnotation(DeprecatedAttr) + def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0) + def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1) + def deprecatedParamName = getAnnotation(DeprecatedNameAttr) flatMap (_ symbolArg 0 orElse Some(nme.NO_NAME)) + def deprecatedParamVersion = getAnnotation(DeprecatedNameAttr) flatMap (_ stringArg 1) def hasDeprecatedInheritanceAnnotation - = hasAnnotation(DeprecatedInheritanceAttr) + = hasAnnotation(DeprecatedInheritanceAttr) def deprecatedInheritanceMessage - = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 0) + = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 0) + def deprecatedInheritanceVersion + = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 1) def hasDeprecatedOverridingAnnotation - = hasAnnotation(DeprecatedOverridingAttr) + = hasAnnotation(DeprecatedOverridingAttr) def deprecatedOverridingMessage - = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 0) + = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 0) + def deprecatedOverridingVersion + = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 1) // !!! when annotation arguments are not literal strings, but any sort of // assembly of strings, there is a fair chance they will turn up here not as diff --git a/test/files/jvm/t8582.check b/test/files/jvm/t8582.check index 0e4da90398e0..0a23cb0c9385 100644 --- a/test/files/jvm/t8582.check +++ b/test/files/jvm/t8582.check @@ -1,4 +1,4 @@ -t8582.scala:17: warning: class BeanInfo in package beans is deprecated: the generation of BeanInfo classes is no longer supported +t8582.scala:17: warning: class BeanInfo in package beans is deprecated (since 2.12.0): the generation of BeanInfo classes is no longer supported class C1 ^ getClass on module gives module class diff --git a/test/files/neg/beanInfoDeprecation.check b/test/files/neg/beanInfoDeprecation.check index 788b277818f0..a91cdabae2ac 100644 --- a/test/files/neg/beanInfoDeprecation.check +++ b/test/files/neg/beanInfoDeprecation.check @@ -1,4 +1,4 @@ -beanInfoDeprecation.scala:2: warning: class BeanInfo in package beans is deprecated: the generation of BeanInfo classes is no longer supported +beanInfoDeprecation.scala:2: warning: class BeanInfo in package beans is deprecated (since 2.12.0): the generation of BeanInfo classes is no longer supported class C ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/classmanifests_new_deprecations.check b/test/files/neg/classmanifests_new_deprecations.check index fd1e2728c31b..1b63303fd4c8 100644 --- a/test/files/neg/classmanifests_new_deprecations.check +++ b/test/files/neg/classmanifests_new_deprecations.check @@ -1,25 +1,25 @@ -classmanifests_new_deprecations.scala:2: warning: type ClassManifest in object Predef is deprecated: Use `scala.reflect.ClassTag` instead +classmanifests_new_deprecations.scala:2: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): Use `scala.reflect.ClassTag` instead def cm1[T: ClassManifest] = ??? ^ -classmanifests_new_deprecations.scala:3: warning: type ClassManifest in object Predef is deprecated: Use `scala.reflect.ClassTag` instead +classmanifests_new_deprecations.scala:3: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): Use `scala.reflect.ClassTag` instead def cm2[T](implicit evidence$1: ClassManifest[T]) = ??? ^ -classmanifests_new_deprecations.scala:4: warning: type ClassManifest in object Predef is deprecated: Use `scala.reflect.ClassTag` instead +classmanifests_new_deprecations.scala:4: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): Use `scala.reflect.ClassTag` instead val cm3: ClassManifest[Int] = null ^ -classmanifests_new_deprecations.scala:6: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:6: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): Use scala.reflect.ClassTag instead def rcm1[T: scala.reflect.ClassManifest] = ??? ^ -classmanifests_new_deprecations.scala:7: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:7: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): Use scala.reflect.ClassTag instead def rcm2[T](implicit evidence$1: scala.reflect.ClassManifest[T]) = ??? ^ -classmanifests_new_deprecations.scala:8: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:8: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): Use scala.reflect.ClassTag instead val rcm3: scala.reflect.ClassManifest[Int] = null ^ -classmanifests_new_deprecations.scala:10: warning: type ClassManifest in object Predef is deprecated: Use `scala.reflect.ClassTag` instead +classmanifests_new_deprecations.scala:10: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): Use `scala.reflect.ClassTag` instead type CM[T] = ClassManifest[T] ^ -classmanifests_new_deprecations.scala:15: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:15: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): Use scala.reflect.ClassTag instead type RCM[T] = scala.reflect.ClassManifest[T] ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/delayed-init-ref.check b/test/files/neg/delayed-init-ref.check index 90bc02796940..1b6ba5c3641f 100644 --- a/test/files/neg/delayed-init-ref.check +++ b/test/files/neg/delayed-init-ref.check @@ -4,7 +4,7 @@ delayed-init-ref.scala:17: warning: Selecting value vall from object O, which ex delayed-init-ref.scala:19: warning: Selecting value vall from object O, which extends scala.DelayedInit, is likely to yield an uninitialized value println(vall) // warn ^ -delayed-init-ref.scala:28: warning: trait DelayedInit in package scala is deprecated: DelayedInit semantics can be surprising. Support for `App` will continue. +delayed-init-ref.scala:28: warning: trait DelayedInit in package scala is deprecated (since 2.11.0): DelayedInit semantics can be surprising. Support for `App` will continue. See the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0-RC1 trait Before extends DelayedInit { ^ diff --git a/test/files/neg/names-defaults-neg-warn.check b/test/files/neg/names-defaults-neg-warn.check index 0f4edef84e55..14a1e50e6892 100644 --- a/test/files/neg/names-defaults-neg-warn.check +++ b/test/files/neg/names-defaults-neg-warn.check @@ -1,7 +1,7 @@ -names-defaults-neg-warn.scala:11: warning: the parameter name s has been deprecated. Use x instead. +names-defaults-neg-warn.scala:11: warning: the parameter name s is deprecated: Use x instead deprNam2.f(s = "dlfkj") ^ -names-defaults-neg-warn.scala:12: warning: the parameter name x has been deprecated. Use s instead. +names-defaults-neg-warn.scala:12: warning: the parameter name x is deprecated: Use s instead deprNam2.g(x = "dlkjf") ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check index 875bc2ade00d..e6929cb52ea6 100644 --- a/test/files/neg/names-defaults-neg.check +++ b/test/files/neg/names-defaults-neg.check @@ -112,16 +112,16 @@ names-defaults-neg.scala:90: error: deprecated parameter name x has to be distin names-defaults-neg.scala:91: error: deprecated parameter name a has to be distinct from any other parameter name (deprecated or not). def deprNam2(a: String)(@deprecatedName('a) b: Int) = 1 ^ -names-defaults-neg.scala:93: warning: the parameter name y has been deprecated. Use b instead. +names-defaults-neg.scala:93: warning: the parameter name y is deprecated: Use b instead deprNam3(y = 10, b = 2) ^ names-defaults-neg.scala:93: error: parameter 'b' is already specified at parameter position 1 deprNam3(y = 10, b = 2) ^ -names-defaults-neg.scala:96: warning: naming parameter deprNam4Arg has been deprecated. +names-defaults-neg.scala:96: warning: naming parameter deprNam4Arg is deprecated. deprNam4(deprNam4Arg = null) ^ -names-defaults-neg.scala:98: warning: naming parameter deprNam5Arg has been deprecated. +names-defaults-neg.scala:98: warning: naming parameter deprNam5Arg is deprecated. deprNam5(deprNam5Arg = null) ^ names-defaults-neg.scala:102: error: unknown parameter name: m diff --git a/test/files/neg/t4851.check b/test/files/neg/t4851.check index d5711a889bf4..ac0854f8105c 100644 --- a/test/files/neg/t4851.check +++ b/test/files/neg/t4851.check @@ -1,10 +1,10 @@ -S.scala:2: warning: Adaptation of argument list by inserting () has been deprecated: leaky (Object-receiving) target makes this especially dangerous. +S.scala:2: warning: Adaptation of argument list by inserting () is deprecated: leaky (Object-receiving) target makes this especially dangerous. signature: J(x: Any): J given arguments: after adaptation: new J((): Unit) val x1 = new J ^ -S.scala:3: warning: Adaptation of argument list by inserting () has been deprecated: leaky (Object-receiving) target makes this especially dangerous. +S.scala:3: warning: Adaptation of argument list by inserting () is deprecated: leaky (Object-receiving) target makes this especially dangerous. signature: J(x: Any): J given arguments: after adaptation: new J((): Unit) @@ -28,13 +28,13 @@ S.scala:7: warning: Adapting argument list by creating a 3-tuple: this may not b after adaptation: new Some((1, 2, 3): (Int, Int, Int)) val y2 = new Some(1, 2, 3) ^ -S.scala:9: warning: Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want. +S.scala:9: warning: Adaptation of argument list by inserting () is deprecated: this is unlikely to be what you want. signature: J2(x: T): J2[T] given arguments: after adaptation: new J2((): Unit) val z1 = new J2 ^ -S.scala:10: warning: Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want. +S.scala:10: warning: Adaptation of argument list by inserting () is deprecated: this is unlikely to be what you want. signature: J2(x: T): J2[T] given arguments: after adaptation: new J2((): Unit) diff --git a/test/files/neg/t6120.check b/test/files/neg/t6120.check index f432fde32f47..b7a5d8bf17a5 100644 --- a/test/files/neg/t6120.check +++ b/test/files/neg/t6120.check @@ -6,13 +6,13 @@ See the Scaladoc for value scala.language.postfixOps for a discussion why the feature should be explicitly enabled. def f = null == null bippy ^ -t6120.scala:5: warning: method bippy in class BooleanOps is deprecated: bobo +t6120.scala:5: warning: method bippy in class BooleanOps is deprecated (since 2.11.0): bobo def f = null == null bippy ^ t6120.scala:5: warning: comparing values of types Null and Null using `==' will always yield true def f = null == null bippy ^ -t6120.scala:6: warning: method bippy in class BooleanOps is deprecated: bobo +t6120.scala:6: warning: method bippy in class BooleanOps is deprecated (since 2.11.0): bobo def g = true.bippy ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/t6162-inheritance.check b/test/files/neg/t6162-inheritance.check index c9f4ddaec14b..9b0a8990da95 100644 --- a/test/files/neg/t6162-inheritance.check +++ b/test/files/neg/t6162-inheritance.check @@ -1,4 +1,4 @@ -usage.scala:3: warning: inheritance from class Foo in package t6126 is deprecated: `Foo` will be made final in a future version. +usage.scala:3: warning: inheritance from class Foo in package t6126 is deprecated (since 2.10.0): `Foo` will be made final in a future version. class SubFoo extends Foo ^ usage.scala:5: warning: inheritance from trait T in package t6126 is deprecated diff --git a/test/files/neg/t6162-overriding.check b/test/files/neg/t6162-overriding.check index 6bff75d88dc4..586bfb4b35fb 100644 --- a/test/files/neg/t6162-overriding.check +++ b/test/files/neg/t6162-overriding.check @@ -1,4 +1,4 @@ -t6162-overriding.scala:14: warning: overriding method bar in class Bar is deprecated: `bar` will be made private in a future version. +t6162-overriding.scala:14: warning: overriding method bar in class Bar is deprecated (since 2.10.0): `bar` will be made private in a future version. override def bar = 43 ^ t6162-overriding.scala:15: warning: overriding method baz in class Bar is deprecated diff --git a/test/files/neg/t6406-regextract.check b/test/files/neg/t6406-regextract.check index 19425a68b051..b49b6656f540 100644 --- a/test/files/neg/t6406-regextract.check +++ b/test/files/neg/t6406-regextract.check @@ -1,4 +1,4 @@ -t6406-regextract.scala:4: warning: method unapplySeq in class Regex is deprecated: Extracting a match result from anything but a CharSequence or Match is deprecated +t6406-regextract.scala:4: warning: method unapplySeq in class Regex is deprecated (since 2.11.0): Extracting a match result from anything but a CharSequence or Match is deprecated List(1) collect { case r(i) => i } ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/t7294b.check b/test/files/neg/t7294b.check index 0033b7212513..707266f0cccf 100644 --- a/test/files/neg/t7294b.check +++ b/test/files/neg/t7294b.check @@ -1,4 +1,4 @@ -t7294b.scala:1: warning: inheritance from class Tuple2 in package scala is deprecated: Tuples will be made final in a future version. +t7294b.scala:1: warning: inheritance from class Tuple2 in package scala is deprecated (since 2.11.0): Tuples will be made final in a future version. class C extends Tuple2[Int, Int](0, 0) ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/t7783.check b/test/files/neg/t7783.check index 647cfee12152..18dc84a8dbe5 100644 --- a/test/files/neg/t7783.check +++ b/test/files/neg/t7783.check @@ -1,16 +1,16 @@ -t7783.scala:1: warning: type D in object O is deprecated: +t7783.scala:1: warning: type D in object O is deprecated (since ): object O { class C; @deprecated("", "") type D = C; def foo: Seq[D] = Nil } ^ -t7783.scala:11: warning: type D in object O is deprecated: +t7783.scala:11: warning: type D in object O is deprecated (since ): type T = O.D ^ -t7783.scala:12: warning: type D in object O is deprecated: +t7783.scala:12: warning: type D in object O is deprecated (since ): locally(null: O.D) ^ -t7783.scala:13: warning: type D in object O is deprecated: +t7783.scala:13: warning: type D in object O is deprecated (since ): val x: O.D = null ^ -t7783.scala:14: warning: type D in object O is deprecated: +t7783.scala:14: warning: type D in object O is deprecated (since ): locally(null.asInstanceOf[O.D]) ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/t8035-deprecated.check b/test/files/neg/t8035-deprecated.check index 01f27e5310e4..35aba5551db1 100644 --- a/test/files/neg/t8035-deprecated.check +++ b/test/files/neg/t8035-deprecated.check @@ -1,16 +1,16 @@ -t8035-deprecated.scala:2: warning: Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want. +t8035-deprecated.scala:2: warning: Adaptation of argument list by inserting () is deprecated: this is unlikely to be what you want. signature: GenSetLike.apply(elem: A): Boolean given arguments: after adaptation: GenSetLike((): Unit) List(1,2,3).toSet() ^ -t8035-deprecated.scala:5: warning: Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want. +t8035-deprecated.scala:5: warning: Adaptation of argument list by inserting () is deprecated: this is unlikely to be what you want. signature: A(x: T): Foo.A[T] given arguments: after adaptation: new A((): Unit) new A ^ -t8035-deprecated.scala:9: warning: Adaptation of argument list by inserting () has been deprecated: leaky (Object-receiving) target makes this especially dangerous. +t8035-deprecated.scala:9: warning: Adaptation of argument list by inserting () is deprecated: leaky (Object-receiving) target makes this especially dangerous. signature: Format.format(x$1: Any): String given arguments: after adaptation: Format.format((): Unit) diff --git a/test/files/neg/t8685.check b/test/files/neg/t8685.check index 1780a20b6eda..685fd2e951b8 100644 --- a/test/files/neg/t8685.check +++ b/test/files/neg/t8685.check @@ -1,43 +1,43 @@ -t8685.scala:6: warning: constructor D in class D is deprecated: ctor D is depr +t8685.scala:6: warning: constructor D in class D is deprecated (since now): ctor D is depr case class D @deprecated("ctor D is depr", since="now") (i: Int) ^ -t8685.scala:35: warning: class C is deprecated: class C is depr +t8685.scala:35: warning: class C is deprecated (since now): class C is depr def f = C(42) ^ -t8685.scala:37: warning: object E is deprecated: module E is depr +t8685.scala:37: warning: object E is deprecated (since now): module E is depr def h = E(42) ^ -t8685.scala:37: warning: class E is deprecated: class E is depr +t8685.scala:37: warning: class E is deprecated (since now): class E is depr def h = E(42) ^ -t8685.scala:38: warning: object F is deprecated: module F is depr +t8685.scala:38: warning: object F is deprecated (since now): module F is depr def i = F.G(42) ^ -t8685.scala:39: warning: object F in object Extra is deprecated: Extra module F is depr +t8685.scala:39: warning: object F in object Extra is deprecated (since now): Extra module F is depr def j = Extra.F.G(42) ^ -t8685.scala:43: warning: value gg in trait Applies is deprecated: member gg +t8685.scala:43: warning: value gg in trait Applies is deprecated (since now): member gg def k = this.gg.H(0) ^ -t8685.scala:45: warning: class K in object J is deprecated: Inner K is depr +t8685.scala:45: warning: class K in object J is deprecated (since now): Inner K is depr def l = J.K(42) ^ -t8685.scala:48: warning: class C is deprecated: class C is depr +t8685.scala:48: warning: class C is deprecated (since now): class C is depr def f = new C(42) ^ -t8685.scala:49: warning: constructor D in class D is deprecated: ctor D is depr +t8685.scala:49: warning: constructor D in class D is deprecated (since now): ctor D is depr def g = new D(42) ^ -t8685.scala:50: warning: class E is deprecated: class E is depr +t8685.scala:50: warning: class E is deprecated (since now): class E is depr def h = new E(42) ^ -t8685.scala:51: warning: object F is deprecated: module F is depr +t8685.scala:51: warning: object F is deprecated (since now): module F is depr def i = new F.G(42) ^ -t8685.scala:52: warning: object F in object Extra is deprecated: Extra module F is depr +t8685.scala:52: warning: object F in object Extra is deprecated (since now): Extra module F is depr def j = new Extra.F.G(42) ^ -t8685.scala:53: warning: class K in object J is deprecated: Inner K is depr +t8685.scala:53: warning: class K in object J is deprecated (since now): Inner K is depr def l = new J.K(42) ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/t9684.check b/test/files/neg/t9684.check index 833ca3341a1d..ab36479a472a 100644 --- a/test/files/neg/t9684.check +++ b/test/files/neg/t9684.check @@ -1,7 +1,7 @@ -t9684.scala:6: warning: object JavaConversions in package collection is deprecated: Use JavaConverters +t9684.scala:6: warning: object JavaConversions in package collection is deprecated (since 2.12): Use JavaConverters null.asInstanceOf[java.util.List[Int]] : Buffer[Int] ^ -t9684.scala:8: warning: object JavaConversions in package collection is deprecated: Use JavaConverters +t9684.scala:8: warning: object JavaConversions in package collection is deprecated (since 2.12): Use JavaConverters null.asInstanceOf[Iterable[Int]] : java.util.Collection[Int] ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/run/t3235-minimal.check b/test/files/run/t3235-minimal.check index d7f716002f0c..5b0657219161 100644 --- a/test/files/run/t3235-minimal.check +++ b/test/files/run/t3235-minimal.check @@ -1,12 +1,12 @@ -t3235-minimal.scala:3: warning: method round in class RichInt is deprecated: This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? +t3235-minimal.scala:3: warning: method round in class RichInt is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? assert(123456789.round == 123456789) ^ -t3235-minimal.scala:4: warning: method round in package math is deprecated: This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? +t3235-minimal.scala:4: warning: method round in package math is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? assert(math.round(123456789) == 123456789) ^ -t3235-minimal.scala:5: warning: method round in class RichLong is deprecated: This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? +t3235-minimal.scala:5: warning: method round in class RichLong is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? assert(1234567890123456789L.round == 1234567890123456789L) ^ -t3235-minimal.scala:6: warning: method round in package math is deprecated: This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? +t3235-minimal.scala:6: warning: method round in package math is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? assert(math.round(1234567890123456789L) == 1234567890123456789L) ^ diff --git a/test/files/run/t4542.check b/test/files/run/t4542.check index 6e099222b08e..942de545b517 100644 --- a/test/files/run/t4542.check +++ b/test/files/run/t4542.check @@ -5,7 +5,7 @@ scala> @deprecated("foooo", "ReplTest version 1.0-FINAL") class Foo() { defined class Foo scala> val f = new Foo -:12: warning: class Foo is deprecated: foooo +:12: warning: class Foo is deprecated (since ReplTest version 1.0-FINAL): foooo val f = new Foo ^ f: Foo = Bippy diff --git a/test/files/run/t4594-repl-settings.scala b/test/files/run/t4594-repl-settings.scala index f2d1a8b3f806..8ececce24af3 100644 --- a/test/files/run/t4594-repl-settings.scala +++ b/test/files/run/t4594-repl-settings.scala @@ -15,7 +15,7 @@ object Test extends SessionTest { |scala> :settings -deprecation | |scala> def b = depp - |:12: warning: method depp is deprecated: Please don't do that. + |:12: warning: method depp is deprecated (since Time began.): Please don't do that. | def b = depp | ^ |b: String diff --git a/test/files/run/toolbox_console_reporter.check b/test/files/run/toolbox_console_reporter.check index 1395c6874072..fca10ba458de 100644 --- a/test/files/run/toolbox_console_reporter.check +++ b/test/files/run/toolbox_console_reporter.check @@ -1,8 +1,8 @@ hello ============compiler console============= -warning: method foo in object Utils is deprecated: test +warning: method foo in object Utils is deprecated (since 2.10.0): test ========================================= ============compiler messages============ -Info(NoPosition,method foo in object Utils is deprecated: test,WARNING) +Info(NoPosition,method foo in object Utils is deprecated (since 2.10.0): test,WARNING) ========================================= diff --git a/test/files/run/toolbox_silent_reporter.check b/test/files/run/toolbox_silent_reporter.check index 2d05b1e3f864..dff89f635fa8 100644 --- a/test/files/run/toolbox_silent_reporter.check +++ b/test/files/run/toolbox_silent_reporter.check @@ -1,4 +1,4 @@ hello ============compiler messages============ -Info(NoPosition,method foo in object Utils is deprecated: test,WARNING) +Info(NoPosition,method foo in object Utils is deprecated (since 2.10.0): test,WARNING) ========================================= From 5562e1a2eb07b9a541b3eac85a809847e2d48763 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Thu, 19 May 2016 14:57:25 +0200 Subject: [PATCH 071/153] Lower-case spelling of @deprecated messages --- .../tools/nsc/typechecker/NamesDefaults.scala | 2 +- src/library/scala/App.scala | 2 +- src/library/scala/Console.scala | 40 +++++----- src/library/scala/DelayedInit.scala | 4 +- src/library/scala/Function.scala | 8 +- src/library/scala/NotNull.scala | 2 +- src/library/scala/Predef.scala | 72 +++++++++--------- src/library/scala/Responder.scala | 4 +- src/library/scala/annotation/bridge.scala | 2 +- .../scala/collection/IterableProxy.scala | 2 +- .../scala/collection/IterableProxyLike.scala | 2 +- src/library/scala/collection/MapProxy.scala | 2 +- .../scala/collection/MapProxyLike.scala | 2 +- src/library/scala/collection/SeqProxy.scala | 2 +- .../scala/collection/SeqProxyLike.scala | 2 +- src/library/scala/collection/SetProxy.scala | 2 +- .../scala/collection/SetProxyLike.scala | 2 +- .../scala/collection/TraversableProxy.scala | 2 +- .../collection/TraversableProxyLike.scala | 2 +- .../scala/collection/concurrent/TrieMap.scala | 10 +-- .../generic/IterableForwarder.scala | 2 +- .../collection/generic/SeqForwarder.scala | 2 +- .../generic/TraversableForwarder.scala | 2 +- .../scala/collection/immutable/MapProxy.scala | 2 +- .../scala/collection/immutable/PagedSeq.scala | 4 +- .../scala/collection/immutable/Range.scala | 16 ++-- .../scala/collection/immutable/SetProxy.scala | 2 +- .../scala/collection/immutable/Stack.scala | 2 +- .../collection/immutable/StringLike.scala | 2 +- .../scala/collection/mutable/BufferLike.scala | 2 +- .../collection/mutable/BufferProxy.scala | 4 +- .../collection/mutable/DefaultMapModel.scala | 2 +- .../collection/mutable/DoubleLinkedList.scala | 4 +- .../mutable/DoubleLinkedListLike.scala | 2 +- .../mutable/ImmutableMapAdaptor.scala | 2 +- .../mutable/ImmutableSetAdaptor.scala | 2 +- .../scala/collection/mutable/LinkedList.scala | 4 +- .../collection/mutable/LinkedListLike.scala | 2 +- .../scala/collection/mutable/MapProxy.scala | 2 +- .../collection/mutable/ObservableBuffer.scala | 5 +- .../collection/mutable/ObservableMap.scala | 5 +- .../collection/mutable/ObservableSet.scala | 5 +- .../collection/mutable/PriorityQueue.scala | 8 +- .../scala/collection/mutable/Queue.scala | 2 +- .../scala/collection/mutable/QueueProxy.scala | 2 +- .../scala/collection/mutable/SetLike.scala | 2 +- .../scala/collection/mutable/SetProxy.scala | 2 +- .../scala/collection/mutable/StackProxy.scala | 2 +- .../mutable/SynchronizedBuffer.scala | 4 +- .../collection/mutable/SynchronizedMap.scala | 4 +- .../mutable/SynchronizedQueue.scala | 2 +- .../collection/mutable/SynchronizedSet.scala | 4 +- .../mutable/SynchronizedStack.scala | 2 +- .../collection/parallel/ParIterableLike.scala | 2 +- .../collection/parallel/TaskSupport.scala | 2 +- .../scala/collection/parallel/Tasks.scala | 10 +-- .../scala/collection/parallel/package.scala | 6 +- .../scala/collection/script/Location.scala | 10 +-- .../scala/collection/script/Message.scala | 12 +-- .../scala/collection/script/Scriptable.scala | 2 +- .../scala/concurrent/ExecutionContext.scala | 2 +- src/library/scala/concurrent/Future.scala | 10 +-- src/library/scala/concurrent/Lock.scala | 2 +- src/library/scala/concurrent/SyncVar.scala | 4 +- .../scala/concurrent/forkjoin/package.scala | 20 ++--- src/library/scala/concurrent/package.scala | 14 ++-- src/library/scala/io/Position.scala | 2 +- src/library/scala/math/BigDecimal.scala | 16 ++-- src/library/scala/math/package.scala | 8 +- .../reflect/ClassManifestDeprecatedApis.scala | 24 +++--- src/library/scala/reflect/Manifest.scala | 4 +- src/library/scala/reflect/package.scala | 6 +- src/library/scala/runtime/RichException.scala | 2 +- src/library/scala/runtime/RichInt.scala | 4 +- src/library/scala/runtime/RichLong.scala | 4 +- .../scala/runtime/SeqCharSequence.scala | 2 +- src/library/scala/runtime/StringAdd.scala | 2 +- src/library/scala/runtime/StringFormat.scala | 2 +- src/library/scala/sys/SystemProperties.scala | 2 +- .../scala/sys/process/ProcessBuilder.scala | 16 ++-- src/library/scala/text/Document.scala | 16 ++-- src/library/scala/util/MurmurHash.scala | 4 +- src/library/scala/util/matching/Regex.scala | 8 +- .../scala/reflect/api/Annotations.scala | 58 +++++++------- src/reflect/scala/reflect/api/FlagSets.scala | 2 +- src/reflect/scala/reflect/api/Internals.scala | 76 +++++++++---------- src/reflect/scala/reflect/api/Names.scala | 12 +-- src/reflect/scala/reflect/api/Position.scala | 32 ++++---- .../scala/reflect/api/StandardNames.scala | 4 +- src/reflect/scala/reflect/api/Symbols.scala | 12 +-- src/reflect/scala/reflect/api/Trees.scala | 54 ++++++------- src/reflect/scala/reflect/api/Types.scala | 38 +++++----- .../reflect/internal/AnnotationCheckers.scala | 6 +- .../scala/reflect/internal/Definitions.scala | 4 +- .../scala/reflect/internal/Flags.scala | 4 +- .../scala/reflect/internal/HasFlags.scala | 4 +- .../scala/reflect/internal/Mirrors.scala | 2 +- .../scala/reflect/internal/Scopes.scala | 2 +- .../scala/reflect/internal/StdNames.scala | 16 ++-- .../scala/reflect/internal/SymbolTable.scala | 4 +- .../scala/reflect/internal/Symbols.scala | 12 +-- .../scala/reflect/internal/Trees.scala | 6 +- .../scala/reflect/internal/Types.scala | 2 +- .../internal/annotations/package.scala | 4 +- .../scala/reflect/internal/tpe/TypeMaps.scala | 2 +- .../reflect/internal/util/Position.scala | 6 +- .../scala/reflect/macros/ExprUtils.scala | 26 +++---- src/reflect/scala/reflect/macros/Names.scala | 6 +- src/reflect/scala/reflect/macros/Typers.scala | 4 +- .../scala/reflect/macros/Universe.scala | 44 +++++------ .../scala/reflect/macros/package.scala | 4 +- .../neg/classmanifests_new_deprecations.check | 16 ++-- test/files/neg/delayed-init-ref.check | 3 +- test/files/neg/names-defaults-neg-warn.check | 4 +- test/files/neg/names-defaults-neg.check | 2 +- test/files/neg/t6406-regextract.check | 2 +- test/files/run/t3235-minimal.check | 8 +- 117 files changed, 484 insertions(+), 490 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 063cfd38054e..d7405c28d532 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -573,7 +573,7 @@ trait NamesDefaults { self: Analyzer => } def checkAltName = { val res = checkDeprecation(false) - if (res) warn(s"the parameter name $name is deprecated$since: Use ${param.name} instead") + if (res) warn(s"the parameter name $name is deprecated$since: use ${param.name} instead") res } !param.isSynthetic && (checkName || checkAltName) diff --git a/src/library/scala/App.scala b/src/library/scala/App.scala index 62245322daec..52ef9ca60f2e 100644 --- a/src/library/scala/App.scala +++ b/src/library/scala/App.scala @@ -59,7 +59,7 @@ trait App extends DelayedInit { * themselves define a `delayedInit` method. * @param body the initialization code to be stored for later execution */ - @deprecated("The delayedInit mechanism will disappear.", "2.11.0") + @deprecated("the delayedInit mechanism will disappear", "2.11.0") override def delayedInit(body: => Unit) { initCode += (() => body) } diff --git a/src/library/scala/Console.scala b/src/library/scala/Console.scala index 0b079aae1590..bc702cfaad41 100644 --- a/src/library/scala/Console.scala +++ b/src/library/scala/Console.scala @@ -287,54 +287,54 @@ private[scala] abstract class DeprecatedConsole { protected def setErrDirect(err: PrintStream): Unit protected def setInDirect(in: BufferedReader): Unit - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readBoolean(): Boolean = StdIn.readBoolean() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readByte(): Byte = StdIn.readByte() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readChar(): Char = StdIn.readChar() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readDouble(): Double = StdIn.readDouble() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readFloat(): Float = StdIn.readFloat() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readInt(): Int = StdIn.readInt() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readLine(): String = StdIn.readLine() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readLine(text: String, args: Any*): String = StdIn.readLine(text, args: _*) - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readLong(): Long = StdIn.readLong() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readShort(): Short = StdIn.readShort() - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readf(format: String): List[Any] = StdIn.readf(format) - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readf1(format: String): Any = StdIn.readf1(format) - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readf2(format: String): (Any, Any) = StdIn.readf2(format) - @deprecated("Use the method in scala.io.StdIn", "2.11.0") def readf3(format: String): (Any, Any, Any) = StdIn.readf3(format) + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readBoolean(): Boolean = StdIn.readBoolean() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readByte(): Byte = StdIn.readByte() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readChar(): Char = StdIn.readChar() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readDouble(): Double = StdIn.readDouble() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readFloat(): Float = StdIn.readFloat() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readInt(): Int = StdIn.readInt() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readLine(): String = StdIn.readLine() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readLine(text: String, args: Any*): String = StdIn.readLine(text, args: _*) + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readLong(): Long = StdIn.readLong() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readShort(): Short = StdIn.readShort() + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readf(format: String): List[Any] = StdIn.readf(format) + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readf1(format: String): Any = StdIn.readf1(format) + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readf2(format: String): (Any, Any) = StdIn.readf2(format) + @deprecated("use the method in scala.io.StdIn", "2.11.0") def readf3(format: String): (Any, Any, Any) = StdIn.readf3(format) /** Sets the default output stream. * * @param out the new output stream. */ - @deprecated("Use withOut", "2.11.0") def setOut(out: PrintStream): Unit = setOutDirect(out) + @deprecated("use withOut", "2.11.0") def setOut(out: PrintStream): Unit = setOutDirect(out) /** Sets the default output stream. * * @param out the new output stream. */ - @deprecated("Use withOut", "2.11.0") def setOut(out: OutputStream): Unit = setOutDirect(new PrintStream(out)) + @deprecated("use withOut", "2.11.0") def setOut(out: OutputStream): Unit = setOutDirect(new PrintStream(out)) /** Sets the default error stream. * * @param err the new error stream. */ - @deprecated("Use withErr", "2.11.0") def setErr(err: PrintStream): Unit = setErrDirect(err) + @deprecated("use withErr", "2.11.0") def setErr(err: PrintStream): Unit = setErrDirect(err) /** Sets the default error stream. * * @param err the new error stream. */ - @deprecated("Use withErr", "2.11.0") def setErr(err: OutputStream): Unit = setErrDirect(new PrintStream(err)) + @deprecated("use withErr", "2.11.0") def setErr(err: OutputStream): Unit = setErrDirect(new PrintStream(err)) /** Sets the default input stream. * * @param reader specifies the new input stream. */ - @deprecated("Use withIn", "2.11.0") def setIn(reader: Reader): Unit = setInDirect(new BufferedReader(reader)) + @deprecated("use withIn", "2.11.0") def setIn(reader: Reader): Unit = setInDirect(new BufferedReader(reader)) /** Sets the default input stream. * * @param in the new input stream. */ - @deprecated("Use withIn", "2.11.0") def setIn(in: InputStream): Unit = setInDirect(new BufferedReader(new InputStreamReader(in))) + @deprecated("use withIn", "2.11.0") def setIn(in: InputStream): Unit = setInDirect(new BufferedReader(new InputStreamReader(in))) } diff --git a/src/library/scala/DelayedInit.scala b/src/library/scala/DelayedInit.scala index 7f976b073f37..8dc841a7e38c 100644 --- a/src/library/scala/DelayedInit.scala +++ b/src/library/scala/DelayedInit.scala @@ -43,7 +43,7 @@ package scala * * @author Martin Odersky */ -@deprecated("DelayedInit semantics can be surprising. Support for `App` will continue.\nSee the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0-RC1", "2.11.0") +@deprecated("DelayedInit semantics can be surprising. Support for `App` will continue. See the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0-RC1", "2.11.0") trait DelayedInit { def delayedInit(x: => Unit): Unit -} \ No newline at end of file +} diff --git a/src/library/scala/Function.scala b/src/library/scala/Function.scala index 7bd12a2719a0..f28897c20bd3 100644 --- a/src/library/scala/Function.scala +++ b/src/library/scala/Function.scala @@ -72,7 +72,7 @@ object Function { * @note These functions are slotted for deprecation, but it is on * hold pending superior type inference for tupling anonymous functions. */ - // @deprecated("Use `f.tupled` instead") + // @deprecated("use `f.tupled` instead") def tupled[a1, a2, b](f: (a1, a2) => b): Tuple2[a1, a2] => b = { case Tuple2(x1, x2) => f(x1, x2) } @@ -80,7 +80,7 @@ object Function { /** Tupling for functions of arity 3. This transforms a function * of arity 3 into a unary function that takes a triple of arguments. */ - // @deprecated("Use `f.tupled` instead") + // @deprecated("use `f.tupled` instead") def tupled[a1, a2, a3, b](f: (a1, a2, a3) => b): Tuple3[a1, a2, a3] => b = { case Tuple3(x1, x2, x3) => f(x1, x2, x3) } @@ -88,7 +88,7 @@ object Function { /** Tupling for functions of arity 4. This transforms a function * of arity 4 into a unary function that takes a 4-tuple of arguments. */ - // @deprecated("Use `f.tupled` instead") + // @deprecated("use `f.tupled` instead") def tupled[a1, a2, a3, a4, b](f: (a1, a2, a3, a4) => b): Tuple4[a1, a2, a3, a4] => b = { case Tuple4(x1, x2, x3, x4) => f(x1, x2, x3, x4) } @@ -96,7 +96,7 @@ object Function { /** Tupling for functions of arity 5. This transforms a function * of arity 5 into a unary function that takes a 5-tuple of arguments. */ - // @deprecated("Use `f.tupled` instead") + // @deprecated("use `f.tupled` instead") def tupled[a1, a2, a3, a4, a5, b](f: (a1, a2, a3, a4, a5) => b): Tuple5[a1, a2, a3, a4, a5] => b = { case Tuple5(x1, x2, x3, x4, x5) => f(x1, x2, x3, x4, x5) } diff --git a/src/library/scala/NotNull.scala b/src/library/scala/NotNull.scala index 3cbe9ed4ac09..6a9be79281ad 100644 --- a/src/library/scala/NotNull.scala +++ b/src/library/scala/NotNull.scala @@ -13,5 +13,5 @@ package scala * @since 2.5 */ -@deprecated("This trait will be removed", "2.11.0") +@deprecated("this trait will be removed", "2.11.0") trait NotNull extends Any {} diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 216f6663b5d5..5f1a6b0bbbd5 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -153,31 +153,31 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { // Manifest types, companions, and incantations for summoning @annotation.implicitNotFound(msg = "No ClassManifest available for ${T}.") - @deprecated("Use `scala.reflect.ClassTag` instead", "2.10.0") + @deprecated("use `scala.reflect.ClassTag` instead", "2.10.0") type ClassManifest[T] = scala.reflect.ClassManifest[T] // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") + // @deprecated("this notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") type OptManifest[T] = scala.reflect.OptManifest[T] @annotation.implicitNotFound(msg = "No Manifest available for ${T}.") // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("Use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") + // @deprecated("use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") type Manifest[T] = scala.reflect.Manifest[T] - @deprecated("Use `scala.reflect.ClassTag` instead", "2.10.0") + @deprecated("use `scala.reflect.ClassTag` instead", "2.10.0") val ClassManifest = scala.reflect.ClassManifest // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("Use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") + // @deprecated("use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") val Manifest = scala.reflect.Manifest // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") + // @deprecated("this notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") val NoManifest = scala.reflect.NoManifest // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("Use scala.reflect.classTag[T] and scala.reflect.runtime.universe.typeTag[T] instead", "2.10.0") + // @deprecated("use scala.reflect.classTag[T] and scala.reflect.runtime.universe.typeTag[T] instead", "2.10.0") def manifest[T](implicit m: Manifest[T]) = m - @deprecated("Use scala.reflect.classTag[T] instead", "2.10.0") + @deprecated("use scala.reflect.classTag[T] instead", "2.10.0") def classManifest[T](implicit m: ClassManifest[T]) = m // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") + // @deprecated("this notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") def optManifest[T](implicit m: OptManifest[T]) = m // Minor variations on identity functions @@ -285,17 +285,17 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { // tupling ------------------------------------------------------------ - @deprecated("Use built-in tuple syntax or Tuple2 instead", "2.11.0") + @deprecated("use built-in tuple syntax or Tuple2 instead", "2.11.0") type Pair[+A, +B] = Tuple2[A, B] - @deprecated("Use built-in tuple syntax or Tuple2 instead", "2.11.0") + @deprecated("use built-in tuple syntax or Tuple2 instead", "2.11.0") object Pair { def apply[A, B](x: A, y: B) = Tuple2(x, y) def unapply[A, B](x: Tuple2[A, B]): Option[Tuple2[A, B]] = Some(x) } - @deprecated("Use built-in tuple syntax or Tuple3 instead", "2.11.0") + @deprecated("use built-in tuple syntax or Tuple3 instead", "2.11.0") type Triple[+A, +B, +C] = Tuple3[A, B, C] - @deprecated("Use built-in tuple syntax or Tuple3 instead", "2.11.0") + @deprecated("use built-in tuple syntax or Tuple3 instead", "2.11.0") object Triple { def apply[A, B, C](x: A, y: B, z: C) = Tuple3(x, y, z) def unapply[A, B, C](x: Tuple3[A, B, C]): Option[Tuple3[A, B, C]] = Some(x) @@ -334,7 +334,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { implicit final class RichException(private val self: Throwable) extends AnyVal { import scala.compat.Platform.EOL - @deprecated("Use Throwable#getStackTrace", "2.11.0") def getStackTraceString = self.getStackTrace().mkString("", EOL, EOL) + @deprecated("use Throwable#getStackTrace", "2.11.0") def getStackTraceString = self.getStackTrace().mkString("", EOL, EOL) } /** @group implicit-classes-char */ @@ -508,7 +508,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { /** @group type-constraints */ implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A] - @deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0") + @deprecated("use `implicitly[T <:< U]` or `identity` instead.", "2.11.0") def conforms[A]: A <:< A = $conforms[A] /** An instance of `A =:= B` witnesses that the types `A` and `B` are equal. @@ -542,27 +542,27 @@ private[scala] trait DeprecatedPredef { self: Predef.type => // Deprecated stubs for any who may have been calling these methods directly. - @deprecated("Use `ArrowAssoc`", "2.11.0") def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) - @deprecated("Use `Ensuring`", "2.11.0") def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x) - @deprecated("Use `StringFormat`", "2.11.0") def any2stringfmt(x: Any): StringFormat[Any] = new StringFormat(x) - @deprecated("Use `Throwable` directly", "2.11.0") def exceptionWrapper(exc: Throwable) = new RichException(exc) - @deprecated("Use `SeqCharSequence`", "2.11.0") def seqToCharSequence(xs: scala.collection.IndexedSeq[Char]): CharSequence = new SeqCharSequence(xs) - @deprecated("Use `ArrayCharSequence`", "2.11.0") def arrayToCharSequence(xs: Array[Char]): CharSequence = new ArrayCharSequence(xs) - - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readLine(): String = StdIn.readLine() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readLine(text: String, args: Any*) = StdIn.readLine(text, args: _*) - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readBoolean() = StdIn.readBoolean() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readByte() = StdIn.readByte() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readShort() = StdIn.readShort() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readChar() = StdIn.readChar() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readInt() = StdIn.readInt() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readLong() = StdIn.readLong() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readFloat() = StdIn.readFloat() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readDouble() = StdIn.readDouble() - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readf(format: String) = StdIn.readf(format) - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readf1(format: String) = StdIn.readf1(format) - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readf2(format: String) = StdIn.readf2(format) - @deprecated("Use the method in `scala.io.StdIn`", "2.11.0") def readf3(format: String) = StdIn.readf3(format) + @deprecated("use `ArrowAssoc`", "2.11.0") def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) + @deprecated("use `Ensuring`", "2.11.0") def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x) + @deprecated("use `StringFormat`", "2.11.0") def any2stringfmt(x: Any): StringFormat[Any] = new StringFormat(x) + @deprecated("use `Throwable` directly", "2.11.0") def exceptionWrapper(exc: Throwable) = new RichException(exc) + @deprecated("use `SeqCharSequence`", "2.11.0") def seqToCharSequence(xs: scala.collection.IndexedSeq[Char]): CharSequence = new SeqCharSequence(xs) + @deprecated("use `ArrayCharSequence`", "2.11.0") def arrayToCharSequence(xs: Array[Char]): CharSequence = new ArrayCharSequence(xs) + + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readLine(): String = StdIn.readLine() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readLine(text: String, args: Any*) = StdIn.readLine(text, args: _*) + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readBoolean() = StdIn.readBoolean() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readByte() = StdIn.readByte() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readShort() = StdIn.readShort() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readChar() = StdIn.readChar() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readInt() = StdIn.readInt() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readLong() = StdIn.readLong() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readFloat() = StdIn.readFloat() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readDouble() = StdIn.readDouble() + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readf(format: String) = StdIn.readf(format) + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readf1(format: String) = StdIn.readf1(format) + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readf2(format: String) = StdIn.readf2(format) + @deprecated("use the method in `scala.io.StdIn`", "2.11.0") def readf3(format: String) = StdIn.readf3(format) } /** The `LowPriorityImplicits` class provides implicit values that diff --git a/src/library/scala/Responder.scala b/src/library/scala/Responder.scala index 8a658e252ad7..eb8260dc9ab8 100644 --- a/src/library/scala/Responder.scala +++ b/src/library/scala/Responder.scala @@ -18,7 +18,7 @@ package scala * @see class Responder * @since 2.1 */ -@deprecated("This object will be removed", "2.11.0") +@deprecated("this object will be removed", "2.11.0") object Responder { /** Creates a responder that answer continuations with the constant `a`. @@ -59,7 +59,7 @@ object Responder { * @version 1.0 * @since 2.1 */ -@deprecated("This class will be removed", "2.11.0") +@deprecated("this class will be removed", "2.11.0") abstract class Responder[+A] extends Serializable { def respond(k: A => Unit): Unit diff --git a/src/library/scala/annotation/bridge.scala b/src/library/scala/annotation/bridge.scala index 9f25e2beb3b7..c0c6dba42439 100644 --- a/src/library/scala/annotation/bridge.scala +++ b/src/library/scala/annotation/bridge.scala @@ -10,5 +10,5 @@ package scala.annotation /** If this annotation is present on a method, it will be treated as a bridge method. */ -@deprecated("Reconsider whether using this annotation will accomplish anything", "2.10.0") +@deprecated("reconsider whether using this annotation will accomplish anything", "2.10.0") private[scala] class bridge extends scala.annotation.StaticAnnotation diff --git a/src/library/scala/collection/IterableProxy.scala b/src/library/scala/collection/IterableProxy.scala index 97aa830c5a0b..5f4d69c4117c 100644 --- a/src/library/scala/collection/IterableProxy.scala +++ b/src/library/scala/collection/IterableProxy.scala @@ -16,5 +16,5 @@ package collection * @version 2.8 * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.3") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.3") trait IterableProxy[+A] extends Iterable[A] with IterableProxyLike[A, Iterable[A]] diff --git a/src/library/scala/collection/IterableProxyLike.scala b/src/library/scala/collection/IterableProxyLike.scala index 334b511fb9ef..f87089cba832 100644 --- a/src/library/scala/collection/IterableProxyLike.scala +++ b/src/library/scala/collection/IterableProxyLike.scala @@ -22,7 +22,7 @@ import generic._ * @version 2.8 * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait IterableProxyLike[+A, +Repr <: IterableLike[A, Repr] with Iterable[A]] extends IterableLike[A, Repr] with TraversableProxyLike[A, Repr] { diff --git a/src/library/scala/collection/MapProxy.scala b/src/library/scala/collection/MapProxy.scala index 26a7c710ee43..2faf6899734f 100644 --- a/src/library/scala/collection/MapProxy.scala +++ b/src/library/scala/collection/MapProxy.scala @@ -17,5 +17,5 @@ package collection * @version 1.0, 21/07/2003 * @since 1 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.3") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.3") trait MapProxy[A, +B] extends Map[A, B] with MapProxyLike[A, B, Map[A, B]] diff --git a/src/library/scala/collection/MapProxyLike.scala b/src/library/scala/collection/MapProxyLike.scala index dd80a538e357..73a69357882d 100644 --- a/src/library/scala/collection/MapProxyLike.scala +++ b/src/library/scala/collection/MapProxyLike.scala @@ -18,7 +18,7 @@ package collection * @version 2.8 * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait MapProxyLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] extends MapLike[A, B, This] with IterableProxyLike[(A, B), This] diff --git a/src/library/scala/collection/SeqProxy.scala b/src/library/scala/collection/SeqProxy.scala index f728ba858542..f2b39c7b55ff 100644 --- a/src/library/scala/collection/SeqProxy.scala +++ b/src/library/scala/collection/SeqProxy.scala @@ -18,5 +18,5 @@ package collection * @version 2.8 * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait SeqProxy[+A] extends Seq[A] with SeqProxyLike[A, Seq[A]] diff --git a/src/library/scala/collection/SeqProxyLike.scala b/src/library/scala/collection/SeqProxyLike.scala index b01d227d10a9..b493c707968e 100644 --- a/src/library/scala/collection/SeqProxyLike.scala +++ b/src/library/scala/collection/SeqProxyLike.scala @@ -23,7 +23,7 @@ import generic._ * @version 2.8 * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait SeqProxyLike[+A, +Repr <: SeqLike[A, Repr] with Seq[A]] extends SeqLike[A, Repr] with IterableProxyLike[A, Repr] { override def size = self.size override def toSeq: Seq[A] = self.toSeq diff --git a/src/library/scala/collection/SetProxy.scala b/src/library/scala/collection/SetProxy.scala index e17fb215b972..4a3fc17a78b1 100644 --- a/src/library/scala/collection/SetProxy.scala +++ b/src/library/scala/collection/SetProxy.scala @@ -17,5 +17,5 @@ package collection * @author Martin Odersky * @version 2.0, 01/01/2007 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.3") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.3") trait SetProxy[A] extends Set[A] with SetProxyLike[A, Set[A]] diff --git a/src/library/scala/collection/SetProxyLike.scala b/src/library/scala/collection/SetProxyLike.scala index 4cd215cd89eb..fa23fe545026 100644 --- a/src/library/scala/collection/SetProxyLike.scala +++ b/src/library/scala/collection/SetProxyLike.scala @@ -17,7 +17,7 @@ package collection * @author Martin Odersky * @version 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait SetProxyLike[A, +This <: SetLike[A, This] with Set[A]] extends SetLike[A, This] with IterableProxyLike[A, This] { def empty: This override def contains(elem: A): Boolean = self.contains(elem) diff --git a/src/library/scala/collection/TraversableProxy.scala b/src/library/scala/collection/TraversableProxy.scala index 9eec685d101d..0c7219c5f943 100644 --- a/src/library/scala/collection/TraversableProxy.scala +++ b/src/library/scala/collection/TraversableProxy.scala @@ -21,5 +21,5 @@ package collection * @version 2.8 * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.3") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.3") trait TraversableProxy[+A] extends Traversable[A] with TraversableProxyLike[A, Traversable[A]] diff --git a/src/library/scala/collection/TraversableProxyLike.scala b/src/library/scala/collection/TraversableProxyLike.scala index fa470ea238d7..c8b641f88bab 100644 --- a/src/library/scala/collection/TraversableProxyLike.scala +++ b/src/library/scala/collection/TraversableProxyLike.scala @@ -24,7 +24,7 @@ import scala.reflect.ClassTag * @version 2.8 * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait TraversableProxyLike[+A, +Repr <: TraversableLike[A, Repr] with Traversable[A]] extends TraversableLike[A, Repr] with Proxy { def self: Repr diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index 5dc01547e6c9..769d7b0dacbf 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -639,7 +639,7 @@ extends scala.collection.concurrent.Map[K, V] private var rootupdater = rtupd def hashing = hashingobj def equality = equalityobj - @deprecated("This field will be made private", "2.12.0") + @deprecated("this field will be made private", "2.12.0") @volatile /*private*/ var root = r def this(hashf: Hashing[K], ef: Equiv[K]) = this( @@ -684,13 +684,13 @@ extends scala.collection.concurrent.Map[K, V] } while (obj != TrieMapSerializationEnd) } - @deprecated("This method will be made private", "2.12.0") + @deprecated("this method will be made private", "2.12.0") /*private*/ def CAS_ROOT(ov: AnyRef, nv: AnyRef) = rootupdater.compareAndSet(this, ov, nv) - @deprecated("This method will be made private", "2.12.0") + @deprecated("this method will be made private", "2.12.0") /*private[collection]*/ def readRoot(abort: Boolean = false): INode[K, V] = RDCSS_READ_ROOT(abort) - @deprecated("This method will be made private", "2.12.0") + @deprecated("this method will be made private", "2.12.0") /*private[concurrent]*/ def RDCSS_READ_ROOT(abort: Boolean = false): INode[K, V] = { val r = /*READ*/root r match { @@ -1085,7 +1085,7 @@ private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: Seq(this) } - @deprecated("This method will be removed", "2.12.0") + @deprecated("this method will be removed", "2.12.0") def printDebug() { println("ctrie iterator") println(stackpos.mkString(",")) diff --git a/src/library/scala/collection/generic/IterableForwarder.scala b/src/library/scala/collection/generic/IterableForwarder.scala index 7387dbe66745..7f6eb6e131be 100644 --- a/src/library/scala/collection/generic/IterableForwarder.scala +++ b/src/library/scala/collection/generic/IterableForwarder.scala @@ -26,7 +26,7 @@ import scala.collection._ * @version 2.8 * @since 2.8 */ -@deprecated("Forwarding is inherently unreliable since it is not automated and methods can be forgotten.", "2.11.0") +@deprecated("forwarding is inherently unreliable since it is not automated and methods can be forgotten", "2.11.0") trait IterableForwarder[+A] extends Iterable[A] with TraversableForwarder[A] { /** The iterable object to which calls are forwarded */ diff --git a/src/library/scala/collection/generic/SeqForwarder.scala b/src/library/scala/collection/generic/SeqForwarder.scala index e21e2ea0168d..cee93d2ddbcf 100644 --- a/src/library/scala/collection/generic/SeqForwarder.scala +++ b/src/library/scala/collection/generic/SeqForwarder.scala @@ -25,7 +25,7 @@ import scala.collection.immutable.Range * @version 2.8 * @since 2.8 */ -@deprecated("Forwarding is inherently unreliable since it is not automated and new methods can be forgotten.", "2.11.0") +@deprecated("forwarding is inherently unreliable since it is not automated and new methods can be forgotten", "2.11.0") trait SeqForwarder[+A] extends Seq[A] with IterableForwarder[A] { protected override def underlying: Seq[A] diff --git a/src/library/scala/collection/generic/TraversableForwarder.scala b/src/library/scala/collection/generic/TraversableForwarder.scala index 359ea402b6d3..b94507d6ef5b 100644 --- a/src/library/scala/collection/generic/TraversableForwarder.scala +++ b/src/library/scala/collection/generic/TraversableForwarder.scala @@ -27,7 +27,7 @@ import scala.reflect.ClassTag * @version 2.8 * @since 2.8 */ -@deprecated("Forwarding is inherently unreliable since it is not automated and new methods can be forgotten.", "2.11.0") +@deprecated("forwarding is inherently unreliable since it is not automated and new methods can be forgotten", "2.11.0") trait TraversableForwarder[+A] extends Traversable[A] { /** The traversable object to which calls are forwarded. */ protected def underlying: Traversable[A] diff --git a/src/library/scala/collection/immutable/MapProxy.scala b/src/library/scala/collection/immutable/MapProxy.scala index d126b9e7a6c5..0d1c17d4b337 100644 --- a/src/library/scala/collection/immutable/MapProxy.scala +++ b/src/library/scala/collection/immutable/MapProxy.scala @@ -23,7 +23,7 @@ package immutable * @version 2.0, 31/12/2006 * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait MapProxy[A, +B] extends Map[A, B] with MapProxyLike[A, B, Map[A, B]] { override def repr = this private def newProxy[B1 >: B](newSelf: Map[A, B1]): MapProxy[A, B1] = diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala index fab5ad47ebf8..01854b17978a 100644 --- a/src/library/scala/collection/immutable/PagedSeq.scala +++ b/src/library/scala/collection/immutable/PagedSeq.scala @@ -22,7 +22,7 @@ import scala.reflect.ClassTag * `fromIterator` and `fromIterable` provide generalised instances of `PagedSeq` * @since 2.7 */ -@deprecated("This object will be moved to the scala-parser-combinators module", "2.11.8") +@deprecated("this object will be moved to the scala-parser-combinators module", "2.11.8") object PagedSeq { final val UndeterminedEnd = Int.MaxValue @@ -126,7 +126,7 @@ import PagedSeq._ * @define mayNotTerminateInf * @define willNotTerminateInf */ -@deprecated("This class will be moved to the scala-parser-combinators module", "2.11.8") +@deprecated("this class will be moved to the scala-parser-combinators module", "2.11.8") class PagedSeq[T: ClassTag] protected( more: (Array[T], Int, Int) => Int, first1: Page[T], diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 47be5b507ebc..36e2fa25dd2e 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -33,7 +33,7 @@ import scala.collection.parallel.immutable.ParRange * `init`) are also permitted on overfull ranges. * * @param start the start of this range. - * @param end the end of the range. For exclusive ranges, e.g. + * @param end the end of the range. For exclusive ranges, e.g. * `Range(0,3)` or `(0 until 3)`, this is one * step past the last one in the range. For inclusive * ranges, e.g. `Range.inclusive(0,3)` or `(0 to 3)`, @@ -80,7 +80,7 @@ extends scala.collection.AbstractSeq[Int] || (start < end && step < 0) || (start == end && !isInclusive) ) - @deprecated("This method will be made private, use `length` instead.", "2.11") + @deprecated("this method will be made private, use `length` instead.", "2.11") final val numRangeElements: Int = { if (step == 0) throw new IllegalArgumentException("step cannot be 0.") else if (isEmpty) 0 @@ -90,8 +90,8 @@ extends scala.collection.AbstractSeq[Int] else len.toInt } } - @deprecated("This method will be made private, use `last` instead.", "2.11") - final val lastElement = + @deprecated("this method will be made private, use `last` instead.", "2.11") + final val lastElement = if (isEmpty) start - step else step match { case 1 => if (isInclusive) end else end-1 @@ -102,8 +102,8 @@ extends scala.collection.AbstractSeq[Int] else if (isInclusive) end else end - step } - - @deprecated("This method will be made private.", "2.11") + + @deprecated("this method will be made private.", "2.11") final val terminalElement = lastElement + step /** The last element of this range. This method will return the correct value @@ -197,7 +197,7 @@ extends scala.collection.AbstractSeq[Int] copy(locationAfterN(n), end, step) } ) - + /** Creates a new range containing the elements starting at `from` up to but not including `until`. * * $doesNotUseBuilders @@ -214,7 +214,7 @@ extends scala.collection.AbstractSeq[Int] if (from >= until) newEmptyRange(fromValue) else new Range.Inclusive(fromValue, locationAfterN(until-1), step) } - + /** Creates a new range containing all the elements of this range except the last one. * * $doesNotUseBuilders diff --git a/src/library/scala/collection/immutable/SetProxy.scala b/src/library/scala/collection/immutable/SetProxy.scala index d505185e1d65..e1cf3620a256 100644 --- a/src/library/scala/collection/immutable/SetProxy.scala +++ b/src/library/scala/collection/immutable/SetProxy.scala @@ -22,7 +22,7 @@ package immutable * * @since 2.8 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") trait SetProxy[A] extends Set[A] with SetProxyLike[A, Set[A]] { override def repr = this private def newProxy[B >: A](newSelf: Set[B]): SetProxy[B] = diff --git a/src/library/scala/collection/immutable/Stack.scala b/src/library/scala/collection/immutable/Stack.scala index 1c28093b2c51..02bdadb5dd11 100644 --- a/src/library/scala/collection/immutable/Stack.scala +++ b/src/library/scala/collection/immutable/Stack.scala @@ -46,7 +46,7 @@ object Stack extends SeqFactory[Stack] { * @define willNotTerminateInf */ @SerialVersionUID(1976480595012942526L) -@deprecated("Stack is an inelegant and potentially poorly-performing wrapper around List. Use List instead: stack push x becomes x :: list; stack.pop is list.tail.", "2.11.0") +@deprecated("Stack is an inelegant and potentially poorly-performing wrapper around List. Use List instead: stack push x becomes x :: list; stack.pop is list.tail.", "2.11.0") class Stack[+A] protected (protected val elems: List[A]) extends AbstractSeq[A] with LinearSeq[A] diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index 3c7507f480da..b468b09a9d1a 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -133,7 +133,7 @@ self => * end characters; i.e., apply `.stripLineEnd` to all lines * returned by `linesWithSeparators`. */ - @deprecated("Use `lines` instead.","2.11.0") + @deprecated("use `lines` instead","2.11.0") def linesIterator: Iterator[String] = linesWithSeparators map (line => new WrappedString(line).stripLineEnd) diff --git a/src/library/scala/collection/mutable/BufferLike.scala b/src/library/scala/collection/mutable/BufferLike.scala index 98c9771a056e..c78d59297be9 100644 --- a/src/library/scala/collection/mutable/BufferLike.scala +++ b/src/library/scala/collection/mutable/BufferLike.scala @@ -187,7 +187,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] * * @param cmd the message to send. */ - @deprecated("Scripting is deprecated.", "2.11.0") + @deprecated("scripting is deprecated", "2.11.0") def <<(cmd: Message[A]): Unit = cmd match { case Include(Start, x) => prepend(x) case Include(End, x) => append(x) diff --git a/src/library/scala/collection/mutable/BufferProxy.scala b/src/library/scala/collection/mutable/BufferProxy.scala index 2d52831d37ac..60f0e297466d 100644 --- a/src/library/scala/collection/mutable/BufferProxy.scala +++ b/src/library/scala/collection/mutable/BufferProxy.scala @@ -26,7 +26,7 @@ import script._ * @define Coll `BufferProxy` * @define coll buffer proxy */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait BufferProxy[A] extends Buffer[A] with Proxy { def self: Buffer[A] @@ -130,7 +130,7 @@ trait BufferProxy[A] extends Buffer[A] with Proxy { * * @param cmd the message to send. */ - @deprecated("Scripting is deprecated.", "2.11.0") + @deprecated("scripting is deprecated", "2.11.0") override def <<(cmd: Message[A]) { self << cmd } /** Return a clone of this buffer. diff --git a/src/library/scala/collection/mutable/DefaultMapModel.scala b/src/library/scala/collection/mutable/DefaultMapModel.scala index 00886205403d..7f832c0766a9 100644 --- a/src/library/scala/collection/mutable/DefaultMapModel.scala +++ b/src/library/scala/collection/mutable/DefaultMapModel.scala @@ -19,7 +19,7 @@ package mutable * @version 1.0, 08/07/2003 * @since 1 */ -@deprecated("This trait will be removed.", "2.11.0") +@deprecated("this trait will be removed", "2.11.0") trait DefaultMapModel[A, B] extends Map[A, B] { type Entry = DefaultEntry[A, B] diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala index fd95e74fbcb2..537cebd90342 100644 --- a/src/library/scala/collection/mutable/DoubleLinkedList.scala +++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala @@ -41,7 +41,7 @@ import generic._ * @define mayNotTerminateInf * @define willNotTerminateInf */ -@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0") +@deprecated("low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features", "2.11.0") @SerialVersionUID(-8144992287952814767L) class DoubleLinkedList[A]() extends AbstractSeq[A] with LinearSeq[A] @@ -78,7 +78,7 @@ class DoubleLinkedList[A]() extends AbstractSeq[A] * @define coll double linked list * @define Coll `DoubleLinkedList` */ -@deprecated("Low-level linked lists are deprecated.", "2.11.0") +@deprecated("low-level linked lists are deprecated", "2.11.0") object DoubleLinkedList extends SeqFactory[DoubleLinkedList] { /** $genericCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, DoubleLinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] diff --git a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala index aafe34f50a60..e85ef05319ca 100644 --- a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala +++ b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala @@ -56,7 +56,7 @@ import scala.annotation.migration * @define Coll `DoubleLinkedList` * @define coll double linked list */ -@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0") +@deprecated("low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features", "2.11.0") trait DoubleLinkedListLike[A, This <: Seq[A] with DoubleLinkedListLike[A, This]] extends SeqLike[A, This] with LinkedListLike[A, This] { self => /** A reference to the node in the linked list preceding the current node. */ diff --git a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala index 9ece8b133584..7ab4dd2d9df2 100644 --- a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala +++ b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala @@ -25,7 +25,7 @@ import scala.annotation.migration * @version 2.0, 01/01/2007 * @since 1 */ -@deprecated("Adaptors are inherently unreliable and prone to performance problems.", "2.11.0") +@deprecated("adaptors are inherently unreliable and prone to performance problems", "2.11.0") class ImmutableMapAdaptor[A, B](protected var imap: immutable.Map[A, B]) extends AbstractMap[A, B] with Map[A, B] diff --git a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala index d7eec70b15f7..aa21c4cc112d 100644 --- a/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala +++ b/src/library/scala/collection/mutable/ImmutableSetAdaptor.scala @@ -20,7 +20,7 @@ package mutable * @version 1.0, 21/07/2003 * @since 1 */ -@deprecated("Adaptors are inherently unreliable and prone to performance problems.", "2.11.0") +@deprecated("adaptors are inherently unreliable and prone to performance problems", "2.11.0") class ImmutableSetAdaptor[A](protected var set: immutable.Set[A]) extends AbstractSet[A] with Set[A] diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala index b3500367af1a..5d03cd44102e 100644 --- a/src/library/scala/collection/mutable/LinkedList.scala +++ b/src/library/scala/collection/mutable/LinkedList.scala @@ -76,7 +76,7 @@ import generic._ * }}} */ @SerialVersionUID(-7308240733518833071L) -@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0") +@deprecated("low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features", "2.11.0") class LinkedList[A]() extends AbstractSeq[A] with LinearSeq[A] with GenericTraversableTemplate[A, LinkedList] @@ -114,7 +114,7 @@ class LinkedList[A]() extends AbstractSeq[A] * @define Coll `LinkedList` * @define coll linked list */ -@deprecated("Low-level linked lists are deprecated.", "2.11.0") +@deprecated("low-level linked lists are deprecated", "2.11.0") object LinkedList extends SeqFactory[LinkedList] { override def empty[A]: LinkedList[A] = new LinkedList[A] implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] diff --git a/src/library/scala/collection/mutable/LinkedListLike.scala b/src/library/scala/collection/mutable/LinkedListLike.scala index d0748b8a9f73..27c4466c9968 100644 --- a/src/library/scala/collection/mutable/LinkedListLike.scala +++ b/src/library/scala/collection/mutable/LinkedListLike.scala @@ -55,7 +55,7 @@ import scala.annotation.tailrec * * }}} */ -@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0") +@deprecated("low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features", "2.11.0") trait LinkedListLike[A, This <: Seq[A] with LinkedListLike[A, This]] extends SeqLike[A, This] { self => var elem: A = _ diff --git a/src/library/scala/collection/mutable/MapProxy.scala b/src/library/scala/collection/mutable/MapProxy.scala index 552cd9769b8f..63b14d328a94 100644 --- a/src/library/scala/collection/mutable/MapProxy.scala +++ b/src/library/scala/collection/mutable/MapProxy.scala @@ -20,7 +20,7 @@ package mutable * @version 2.0, 31/12/2006 * @since 1 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait MapProxy[A, B] extends Map[A, B] with MapProxyLike[A, B, Map[A, B]] { private def newProxy[B1 >: B](newSelf: Map[A, B1]): MapProxy[A, B1] = new MapProxy[A, B1] { val self = newSelf } diff --git a/src/library/scala/collection/mutable/ObservableBuffer.scala b/src/library/scala/collection/mutable/ObservableBuffer.scala index 9c3247f83b61..53d26f4c6f00 100644 --- a/src/library/scala/collection/mutable/ObservableBuffer.scala +++ b/src/library/scala/collection/mutable/ObservableBuffer.scala @@ -23,9 +23,8 @@ import script._ * @version 1.0, 08/07/2003 * @since 1 */ -@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0") -trait ObservableBuffer[A] extends Buffer[A] with Publisher[Message[A] with Undoable] -{ +@deprecated("observables are deprecated because scripting is deprecated", "2.11.0") +trait ObservableBuffer[A] extends Buffer[A] with Publisher[Message[A] with Undoable] { type Pub <: ObservableBuffer[A] abstract override def +=(element: A): this.type = { diff --git a/src/library/scala/collection/mutable/ObservableMap.scala b/src/library/scala/collection/mutable/ObservableMap.scala index 7509b725688b..421302b70036 100644 --- a/src/library/scala/collection/mutable/ObservableMap.scala +++ b/src/library/scala/collection/mutable/ObservableMap.scala @@ -25,9 +25,8 @@ import script._ * @version 2.0, 31/12/2006 * @since 1 */ -@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0") -trait ObservableMap[A, B] extends Map[A, B] with Publisher[Message[(A, B)] with Undoable] -{ +@deprecated("observables are deprecated because scripting is deprecated", "2.11.0") +trait ObservableMap[A, B] extends Map[A, B] with Publisher[Message[(A, B)] with Undoable] { type Pub <: ObservableMap[A, B] diff --git a/src/library/scala/collection/mutable/ObservableSet.scala b/src/library/scala/collection/mutable/ObservableSet.scala index 19b4a5e39f3f..eb55a1f822a5 100644 --- a/src/library/scala/collection/mutable/ObservableSet.scala +++ b/src/library/scala/collection/mutable/ObservableSet.scala @@ -23,9 +23,8 @@ import script._ * @version 1.0, 08/07/2003 * @since 1 */ -@deprecated("Observables are deprecated because scripting is deprecated.", "2.11.0") -trait ObservableSet[A] extends Set[A] with Publisher[Message[A] with Undoable] -{ +@deprecated("observables are deprecated because scripting is deprecated", "2.11.0") +trait ObservableSet[A] extends Set[A] with Publisher[Message[A] with Undoable] { type Pub <: ObservableSet[A] diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index a6c0fc207791..107a2bfa0e88 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -360,10 +360,8 @@ object PriorityQueue extends OrderedTraversableFactory[PriorityQueue] { * @version 1.0, 03/05/2004 * @since 1 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") -sealed abstract class PriorityQueueProxy[A](implicit ord: Ordering[A]) extends PriorityQueue[A] - with Proxy -{ +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") +sealed abstract class PriorityQueueProxy[A](implicit ord: Ordering[A]) extends PriorityQueue[A] with Proxy { def self: PriorityQueue[A] /** Creates a new iterator over all elements contained in this @@ -449,7 +447,7 @@ sealed abstract class PriorityQueueProxy[A](implicit ord: Ordering[A]) extends P * @define Coll `SynchronizedPriorityQueue` * @define coll synchronized priority queue */ -@deprecated("Comprehensive synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentSkipListSet as an alternative.", "2.11.0") +@deprecated("Comprehensive synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentSkipListSet as an alternative.", "2.11.0") sealed class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQueue[A] { /** Checks if the queue is empty. diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index ad60173b641c..fd5fe9aecc9c 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -143,7 +143,7 @@ extends MutableList[A] /** Return the proper suffix of this list which starts with the first element that satisfies `p`. * That element is unlinked from the list. If no element satisfies `p`, return None. */ - @deprecated("extractFirst inappropriately exposes implementation details. Use dequeue or dequeueAll.", "2.11.0") + @deprecated("extractFirst inappropriately exposes implementation details. Use dequeue or dequeueAll.", "2.11.0") def extractFirst(start: LinkedList[A], p: A => Boolean): Option[LinkedList[A]] = { if (isEmpty) None else { diff --git a/src/library/scala/collection/mutable/QueueProxy.scala b/src/library/scala/collection/mutable/QueueProxy.scala index 22ff3306d541..e780cc2cf05f 100644 --- a/src/library/scala/collection/mutable/QueueProxy.scala +++ b/src/library/scala/collection/mutable/QueueProxy.scala @@ -21,7 +21,7 @@ package mutable * @version 1.1, 03/05/2004 * @since 1 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait QueueProxy[A] extends Queue[A] with Proxy { def self: Queue[A] diff --git a/src/library/scala/collection/mutable/SetLike.scala b/src/library/scala/collection/mutable/SetLike.scala index a19130e74207..0797a8315461 100644 --- a/src/library/scala/collection/mutable/SetLike.scala +++ b/src/library/scala/collection/mutable/SetLike.scala @@ -224,7 +224,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]] * @throws UnsupportedOperationException * if the message was not understood. */ - @deprecated("Scripting is deprecated.", "2.11.0") + @deprecated("scripting is deprecated", "2.11.0") def <<(cmd: Message[A]): Unit = cmd match { case Include(_, x) => this += x case Remove(_, x) => this -= x diff --git a/src/library/scala/collection/mutable/SetProxy.scala b/src/library/scala/collection/mutable/SetProxy.scala index 74279507ff12..43b6aa57af68 100644 --- a/src/library/scala/collection/mutable/SetProxy.scala +++ b/src/library/scala/collection/mutable/SetProxy.scala @@ -18,7 +18,7 @@ package mutable * @version 1.1, 09/05/2004 * @since 1 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait SetProxy[A] extends Set[A] with SetProxyLike[A, Set[A]] { override def repr = this override def empty = new SetProxy[A] { val self = SetProxy.this.self.empty } diff --git a/src/library/scala/collection/mutable/StackProxy.scala b/src/library/scala/collection/mutable/StackProxy.scala index 81e63b05d27d..ac52bbba2197 100644 --- a/src/library/scala/collection/mutable/StackProxy.scala +++ b/src/library/scala/collection/mutable/StackProxy.scala @@ -19,7 +19,7 @@ package mutable * @version 1.0, 10/05/2004 * @since 1 */ -@deprecated("Proxying is deprecated due to lack of use and compiler-level support.", "2.11.0") +@deprecated("proxying is deprecated due to lack of use and compiler-level support", "2.11.0") trait StackProxy[A] extends Stack[A] with Proxy { def self: Stack[A] diff --git a/src/library/scala/collection/mutable/SynchronizedBuffer.scala b/src/library/scala/collection/mutable/SynchronizedBuffer.scala index 8c646b0ce514..9c27f8b003f9 100644 --- a/src/library/scala/collection/mutable/SynchronizedBuffer.scala +++ b/src/library/scala/collection/mutable/SynchronizedBuffer.scala @@ -25,7 +25,7 @@ import script._ * @define Coll `SynchronizedBuffer` * @define coll synchronized buffer */ -@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0") +@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0") trait SynchronizedBuffer[A] extends Buffer[A] { import scala.collection.Traversable @@ -162,7 +162,7 @@ trait SynchronizedBuffer[A] extends Buffer[A] { super.clear() } - @deprecated("Scripting is deprecated.", "2.11.0") + @deprecated("scripting is deprecated", "2.11.0") override def <<(cmd: Message[A]): Unit = synchronized { super.<<(cmd) } diff --git a/src/library/scala/collection/mutable/SynchronizedMap.scala b/src/library/scala/collection/mutable/SynchronizedMap.scala index 9876296ebe45..8618798dbd95 100644 --- a/src/library/scala/collection/mutable/SynchronizedMap.scala +++ b/src/library/scala/collection/mutable/SynchronizedMap.scala @@ -24,7 +24,7 @@ import scala.annotation.migration * @define Coll `SynchronizedMap` * @define coll synchronized map */ -@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap as an alternative.", "2.11.0") +@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap as an alternative.", "2.11.0") trait SynchronizedMap[A, B] extends Map[A, B] { abstract override def get(key: A): Option[B] = synchronized { super.get(key) } @@ -54,7 +54,7 @@ trait SynchronizedMap[A, B] extends Map[A, B] { override def contains(key: A): Boolean = synchronized {super.contains(key) } override def isDefinedAt(key: A) = synchronized { super.isDefinedAt(key) } - // @deprecated("See Map.+ for explanation") override def +(kv: (A, B)): this.type = synchronized[this.type] { super.+(kv) } + // @deprecated("see Map.+ for explanation") override def +(kv: (A, B)): this.type = synchronized[this.type] { super.+(kv) } // can't override -, -- same type! // @deprecated override def -(key: A): Self = synchronized { super.-(key) } diff --git a/src/library/scala/collection/mutable/SynchronizedQueue.scala b/src/library/scala/collection/mutable/SynchronizedQueue.scala index 48e40ab27f5a..ee44f07df214 100644 --- a/src/library/scala/collection/mutable/SynchronizedQueue.scala +++ b/src/library/scala/collection/mutable/SynchronizedQueue.scala @@ -25,7 +25,7 @@ package mutable * @define Coll `SynchronizedQueue` * @define coll synchronized queue */ -@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0") +@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.ConcurrentLinkedQueue as an alternative.", "2.11.0") class SynchronizedQueue[A] extends Queue[A] { /** Checks if the queue is empty. * diff --git a/src/library/scala/collection/mutable/SynchronizedSet.scala b/src/library/scala/collection/mutable/SynchronizedSet.scala index dd842f26cebf..399630eb3c72 100644 --- a/src/library/scala/collection/mutable/SynchronizedSet.scala +++ b/src/library/scala/collection/mutable/SynchronizedSet.scala @@ -24,7 +24,7 @@ import script._ * @define Coll `SynchronizedSet` * @define coll synchronized set */ -@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap[A,Unit] as an alternative.", "2.11.0") +@deprecated("Synchronization via traits is deprecated as it is inherently unreliable. Consider java.util.concurrent.ConcurrentHashMap[A,Unit] as an alternative.", "2.11.0") trait SynchronizedSet[A] extends Set[A] { abstract override def size: Int = synchronized { super.size @@ -94,7 +94,7 @@ trait SynchronizedSet[A] extends Set[A] { super.toString } - @deprecated("Scripting is deprecated.", "2.11.0") + @deprecated("scripting is deprecated", "2.11.0") override def <<(cmd: Message[A]): Unit = synchronized { super.<<(cmd) } diff --git a/src/library/scala/collection/mutable/SynchronizedStack.scala b/src/library/scala/collection/mutable/SynchronizedStack.scala index c77a6fad620c..2954a1f768b6 100644 --- a/src/library/scala/collection/mutable/SynchronizedStack.scala +++ b/src/library/scala/collection/mutable/SynchronizedStack.scala @@ -25,7 +25,7 @@ package mutable * @define Coll `SynchronizedStack` * @define coll synchronized stack */ -@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.LinkedBlockingDequeue instead.", "2.11.0") +@deprecated("Synchronization via selective overriding of methods is inherently unreliable. Consider java.util.concurrent.LinkedBlockingDequeue instead.", "2.11.0") class SynchronizedStack[A] extends Stack[A] { /** Checks if the stack is empty. diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala index 2ed7bc075e07..2e60089df5d6 100644 --- a/src/library/scala/collection/parallel/ParIterableLike.scala +++ b/src/library/scala/collection/parallel/ParIterableLike.scala @@ -842,7 +842,7 @@ self: ParIterableLike[T, Repr, Sequential] => tasksupport.executeAndWaitResult(new ToParMap(combinerFactory(cbf), splitter)(ev) mapResult { _.resultWithTaskSupport }) } - @deprecated("Use .seq.view instead", "2.11.0") + @deprecated("use .seq.view instead", "2.11.0") def view = seq.view override def toArray[U >: T: ClassTag]: Array[U] = { diff --git a/src/library/scala/collection/parallel/TaskSupport.scala b/src/library/scala/collection/parallel/TaskSupport.scala index 6ab694de04c5..728605af7b93 100644 --- a/src/library/scala/collection/parallel/TaskSupport.scala +++ b/src/library/scala/collection/parallel/TaskSupport.scala @@ -60,7 +60,7 @@ extends TaskSupport with AdaptiveWorkStealingForkJoinTasks * * @see [[scala.collection.parallel.TaskSupport]] for more information. */ -@deprecated("Use `ForkJoinTaskSupport` instead.", "2.11.0") +@deprecated("use `ForkJoinTaskSupport` instead", "2.11.0") class ThreadPoolTaskSupport(val environment: ThreadPoolExecutor = ThreadPoolTasks.defaultThreadPool) extends TaskSupport with AdaptiveWorkStealingThreadPoolTasks diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala index 2a4e40dd1617..f472c6be5c77 100644 --- a/src/library/scala/collection/parallel/Tasks.scala +++ b/src/library/scala/collection/parallel/Tasks.scala @@ -208,7 +208,7 @@ trait AdaptiveWorkStealingTasks extends Tasks { /** An implementation of tasks objects based on the Java thread pooling API. */ -@deprecated("Use `ForkJoinTasks` instead.", "2.11.0") +@deprecated("use `ForkJoinTasks` instead", "2.11.0") trait ThreadPoolTasks extends Tasks { import java.util.concurrent._ @@ -317,7 +317,7 @@ trait ThreadPoolTasks extends Tasks { } -@deprecated("Use `ForkJoinTasks` instead.", "2.11.0") +@deprecated("use `ForkJoinTasks` instead", "2.11.0") object ThreadPoolTasks { import java.util.concurrent._ @@ -445,7 +445,7 @@ trait AdaptiveWorkStealingForkJoinTasks extends ForkJoinTasks with AdaptiveWorkS def newWrappedTask[R, Tp](b: Task[R, Tp]) = new WrappedTask[R, Tp](b) } -@deprecated("Use `AdaptiveWorkStealingForkJoinTasks` instead.", "2.11.0") +@deprecated("use `AdaptiveWorkStealingForkJoinTasks` instead", "2.11.0") trait AdaptiveWorkStealingThreadPoolTasks extends ThreadPoolTasks with AdaptiveWorkStealingTasks { class WrappedTask[R, Tp](val body: Task[R, Tp]) @@ -523,7 +523,7 @@ private[parallel] final class FutureTasks(executor: ExecutionContext) extends Ta } /** This tasks implementation uses execution contexts to spawn a parallel computation. - * + * * As an optimization, it internally checks whether the execution context is the * standard implementation based on fork/join pools, and if it is, creates a * `ForkJoinTaskSupport` that shares the same pool to forward its request to it. @@ -537,7 +537,7 @@ trait ExecutionContextTasks extends Tasks { val environment: ExecutionContext /** A driver serves as a target for this proxy `Tasks` object. - * + * * If the execution context has the standard implementation and uses fork/join pools, * the driver is `ForkJoinTaskSupport` with the same pool, as an optimization. * Otherwise, the driver will be a Scala `Future`-based implementation. diff --git a/src/library/scala/collection/parallel/package.scala b/src/library/scala/collection/parallel/package.scala index ba64ca505b99..eaa87b675af8 100644 --- a/src/library/scala/collection/parallel/package.scala +++ b/src/library/scala/collection/parallel/package.scala @@ -114,9 +114,9 @@ package parallel { def ifParSeq[R](isbody: ParSeq[T] => R): Otherwise[R] } - @deprecated("This trait will be removed.", "2.11.0") + @deprecated("this trait will be removed", "2.11.0") trait ThrowableOps { - @deprecated("This method will be removed.", "2.11.0") + @deprecated("this method will be removed", "2.11.0") def alongWith(that: Throwable): Throwable } @@ -135,7 +135,7 @@ package parallel { } /** Composite throwable - thrown when multiple exceptions are thrown at the same time. */ - @deprecated("This class will be removed.", "2.11.0") + @deprecated("this class will be removed.", "2.11.0") final case class CompositeThrowable(throwables: Set[Throwable]) extends Exception( "Multiple exceptions thrown during a parallel computation: " + throwables.map(t => t + "\n" + t.getStackTrace.take(10).++("...").mkString("\n")).mkString("\n\n") diff --git a/src/library/scala/collection/script/Location.scala b/src/library/scala/collection/script/Location.scala index bed74bf9ca9f..8a0b10c331ee 100644 --- a/src/library/scala/collection/script/Location.scala +++ b/src/library/scala/collection/script/Location.scala @@ -18,17 +18,17 @@ package script * @since 2.8 */ -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") sealed abstract class Location -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") case object Start extends Location -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") case object End extends Location -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") case object NoLo extends Location -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") case class Index(n: Int) extends Location diff --git a/src/library/scala/collection/script/Message.scala b/src/library/scala/collection/script/Message.scala index 3fc2a0ec7e18..a6ba9d95233e 100644 --- a/src/library/scala/collection/script/Message.scala +++ b/src/library/scala/collection/script/Message.scala @@ -21,7 +21,7 @@ import mutable.ArrayBuffer * @version 1.0, 08/07/2003 * @since 2.8 */ -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") trait Message[+A] /** This observable update refers to inclusion operations that add new elements @@ -30,7 +30,7 @@ trait Message[+A] * @author Matthias Zenger * @version 1.0, 08/07/2003 */ -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") case class Include[+A](location: Location, elem: A) extends Message[A] { def this(elem: A) = this(NoLo, elem) } @@ -41,7 +41,7 @@ case class Include[+A](location: Location, elem: A) extends Message[A] { * @author Matthias Zenger * @version 1.0, 08/07/2003 */ -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") case class Update[+A](location: Location, elem: A) extends Message[A] { def this(elem: A) = this(NoLo, elem) } @@ -52,7 +52,7 @@ case class Update[+A](location: Location, elem: A) extends Message[A] { * @author Matthias Zenger * @version 1.0, 08/07/2003 */ -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") case class Remove[+A](location: Location, elem: A) extends Message[A] { def this(elem: A) = this(NoLo, elem) } @@ -62,7 +62,7 @@ case class Remove[+A](location: Location, elem: A) extends Message[A] { * @author Matthias Zenger * @version 1.0, 08/07/2003 */ -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") case class Reset[+A]() extends Message[A] /** Objects of this class represent compound messages consisting @@ -71,7 +71,7 @@ case class Reset[+A]() extends Message[A] * @author Matthias Zenger * @version 1.0, 10/05/2004 */ -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") class Script[A] extends ArrayBuffer[Message[A]] with Message[A] { override def toString(): String = { diff --git a/src/library/scala/collection/script/Scriptable.scala b/src/library/scala/collection/script/Scriptable.scala index 4db75ddd3ef6..8965286b0db0 100644 --- a/src/library/scala/collection/script/Scriptable.scala +++ b/src/library/scala/collection/script/Scriptable.scala @@ -17,7 +17,7 @@ package script * @version 1.0, 09/05/2004 * @since 2.8 */ -@deprecated("Scripting is deprecated.", "2.11.0") +@deprecated("scripting is deprecated", "2.11.0") trait Scriptable[A] { /** Send a message to this scriptable object. */ diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index e022b94ea8ef..f2c3284f9236 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -87,7 +87,7 @@ trait ExecutionContext { * constructed, so that it doesn't need any additional * preparation later. */ - @deprecated("Preparation of ExecutionContexts will be removed.", "2.12") + @deprecated("preparation of ExecutionContexts will be removed", "2.12") def prepare(): ExecutionContext = this } diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index 8abd7feeb7ac..93e9fddcb3a8 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -274,8 +274,8 @@ trait Future[+T] extends Awaitable[T] { * val g = f map { x: String => x + " is now!" } * }}} * - * Note that a for comprehension involving a `Future` - * may expand to include a call to `map` and or `flatMap` + * Note that a for comprehension involving a `Future` + * may expand to include a call to `map` and or `flatMap` * and `withFilter`. See [[scala.concurrent.Future#flatMap]] for an example of such a comprehension. * * @@ -688,7 +688,7 @@ object Future { * @param p the predicate which indicates if it's a match * @return the `Future` holding the optional result of the search */ - @deprecated("Use the overloaded version of this method that takes a scala.collection.immutable.Iterable instead", "2.12") + @deprecated("use the overloaded version of this method that takes a scala.collection.immutable.Iterable instead", "2.12") def find[T](@deprecatedName('futurestravonce) futures: TraversableOnce[Future[T]])(@deprecatedName('predicate) p: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]] = { val futuresBuffer = futures.toBuffer if (futuresBuffer.isEmpty) successful[Option[T]](None) @@ -775,7 +775,7 @@ object Future { * @param op the fold operation to be applied to the zero and futures * @return the `Future` holding the result of the fold */ - @deprecated("Use Future.foldLeft instead", "2.12") + @deprecated("use Future.foldLeft instead", "2.12") def fold[T, R](futures: TraversableOnce[Future[T]])(zero: R)(@deprecatedName('foldFun) op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = { if (futures.isEmpty) successful(zero) else sequence(futures).map(_.foldLeft(zero)(op)) @@ -794,7 +794,7 @@ object Future { * @param op the reduce operation which is applied to the results of the futures * @return the `Future` holding the result of the reduce */ - @deprecated("Use Future.reduceLeft instead", "2.12") + @deprecated("use Future.reduceLeft instead", "2.12") def reduce[T, R >: T](futures: TraversableOnce[Future[T]])(op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = { if (futures.isEmpty) failed(new NoSuchElementException("reduce attempted on empty collection")) else sequence(futures).map(_ reduceLeft op) diff --git a/src/library/scala/concurrent/Lock.scala b/src/library/scala/concurrent/Lock.scala index 8d18da2d387f..757fb94cc774 100644 --- a/src/library/scala/concurrent/Lock.scala +++ b/src/library/scala/concurrent/Lock.scala @@ -15,7 +15,7 @@ package scala.concurrent * @author Martin Odersky * @version 1.0, 10/03/2003 */ -@deprecated("Use java.util.concurrent.locks.Lock", "2.11.2") +@deprecated("use java.util.concurrent.locks.Lock", "2.11.2") class Lock { var available = true diff --git a/src/library/scala/concurrent/SyncVar.scala b/src/library/scala/concurrent/SyncVar.scala index 127e6b58d269..5fabf553bd5c 100644 --- a/src/library/scala/concurrent/SyncVar.scala +++ b/src/library/scala/concurrent/SyncVar.scala @@ -91,7 +91,7 @@ class SyncVar[A] { // [Heather] the reason why: it doesn't take into consideration // whether or not the SyncVar is already defined. So, set has been // deprecated in order to eventually be able to make "setting" private - @deprecated("Use `put` instead, as `set` is potentially error-prone", "2.10.0") + @deprecated("use `put` instead, as `set` is potentially error-prone", "2.10.0") // NOTE: Used by SBT 0.13.0-M2 and below def set(x: A): Unit = setVal(x) @@ -111,7 +111,7 @@ class SyncVar[A] { // [Heather] the reason why: it doesn't take into consideration // whether or not the SyncVar is already defined. So, unset has been // deprecated in order to eventually be able to make "unsetting" private - @deprecated("Use `take` instead, as `unset` is potentially error-prone", "2.10.0") + @deprecated("use `take` instead, as `unset` is potentially error-prone", "2.10.0") // NOTE: Used by SBT 0.13.0-M2 and below def unset(): Unit = synchronized { isDefined = false diff --git a/src/library/scala/concurrent/forkjoin/package.scala b/src/library/scala/concurrent/forkjoin/package.scala index 7f4524fccf16..1915e25d7b8d 100644 --- a/src/library/scala/concurrent/forkjoin/package.scala +++ b/src/library/scala/concurrent/forkjoin/package.scala @@ -11,9 +11,9 @@ import java.util.{concurrent => juc} import java.util.Collection package object forkjoin { - @deprecated("Use java.util.concurrent.ForkJoinPool directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.ForkJoinPool directly, instead of this alias", "2.12.0") type ForkJoinPool = juc.ForkJoinPool - @deprecated("Use java.util.concurrent.ForkJoinPool directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.ForkJoinPool directly, instead of this alias", "2.12.0") object ForkJoinPool { type ForkJoinWorkerThreadFactory = juc.ForkJoinPool.ForkJoinWorkerThreadFactory type ManagedBlocker = juc.ForkJoinPool.ManagedBlocker @@ -22,9 +22,9 @@ package object forkjoin { def managedBlock(blocker: ManagedBlocker): Unit = juc.ForkJoinPool.managedBlock(blocker) } - @deprecated("Use java.util.concurrent.ForkJoinTask directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.ForkJoinTask directly, instead of this alias", "2.12.0") type ForkJoinTask[T] = juc.ForkJoinTask[T] - @deprecated("Use java.util.concurrent.ForkJoinTask directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.ForkJoinTask directly, instead of this alias", "2.12.0") object ForkJoinTask { def adapt(runnable: Runnable): ForkJoinTask[_] = juc.ForkJoinTask.adapt(runnable) def adapt[T](callable: juc.Callable[_ <: T]): ForkJoinTask[T] = juc.ForkJoinTask.adapt(callable) @@ -39,18 +39,18 @@ package object forkjoin { def invokeAll[T](tasks: ForkJoinTask[T]*): Unit = juc.ForkJoinTask.invokeAll(tasks: _*) } - @deprecated("Use java.util.concurrent.ForkJoinWorkerThread directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.ForkJoinWorkerThread directly, instead of this alias", "2.12.0") type ForkJoinWorkerThread = juc.ForkJoinWorkerThread - @deprecated("Use java.util.concurrent.LinkedTransferQueue directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.LinkedTransferQueue directly, instead of this alias", "2.12.0") type LinkedTransferQueue[T] = juc.LinkedTransferQueue[T] - @deprecated("Use java.util.concurrent.RecursiveAction directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.RecursiveAction directly, instead of this alias", "2.12.0") type RecursiveAction = juc.RecursiveAction - @deprecated("Use java.util.concurrent.RecursiveTask directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.RecursiveTask directly, instead of this alias", "2.12.0") type RecursiveTask[T] = juc.RecursiveTask[T] - @deprecated("Use java.util.concurrent.ThreadLocalRandom directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.ThreadLocalRandom directly, instead of this alias", "2.12.0") type ThreadLocalRandom = juc.ThreadLocalRandom - @deprecated("Use java.util.concurrent.ThreadLocalRandom directly, instead of this alias.", "2.12.0") + @deprecated("use java.util.concurrent.ThreadLocalRandom directly, instead of this alias", "2.12.0") object ThreadLocalRandom { // For source compatibility, current must declare the empty argument list. // Having no argument list makes more sense since it doesn't have any side effects, diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index d159dda414a9..667a7547ac58 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -20,11 +20,11 @@ import scala.annotation.implicitNotFound * [[http://docs.scala-lang.org/overviews/core/futures.html]]. * * == Common Imports == - * + * * When working with Futures, you will often find that importing the whole concurrent * package is convenient, furthermore you are likely to need an implicit ExecutionContext * in scope for many operations involving Futures and Promises: - * + * * {{{ * import scala.concurrent._ * import ExecutionContext.Implicits.global @@ -41,7 +41,7 @@ import scala.annotation.implicitNotFound * }}} * * == Using Futures For Non-blocking Computation == - * + * * Basic use of futures is easy with the factory method on Future, which executes a * provided function asynchronously, handing you back a future result of that function * without blocking the current thread. In order to create the Future you will need @@ -50,7 +50,7 @@ import scala.annotation.implicitNotFound * {{{ * import scala.concurrent._ * import ExecutionContext.Implicits.global // implicit execution context - * + * * val firstZebra: Future[Int] = Future { * val source = scala.io.Source.fromFile("/etc/dictionaries-common/words") * source.toSeq.indexOfSlice("zebra") @@ -80,7 +80,7 @@ import scala.annotation.implicitNotFound * animalRange.onSuccess { * case x if x > 500000 => println("It's a long way from Aardvark to Zebra") * } - * }}} + * }}} */ package object concurrent { type ExecutionException = java.util.concurrent.ExecutionException @@ -96,7 +96,7 @@ package object concurrent { * @param executor the execution context on which the future is run * @return the `Future` holding the result of the computation */ - @deprecated("Use `Future { ... }` instead.", "2.11.0") + @deprecated("use `Future { ... }` instead", "2.11.0") // removal planned for 2.13.0 def future[T](body: =>T)(implicit @deprecatedName('execctx) executor: ExecutionContext): Future[T] = Future[T](body) @@ -105,7 +105,7 @@ package object concurrent { * @tparam T the type of the value in the promise * @return the newly created `Promise` object */ - @deprecated("Use `Promise[T]()` instead.", "2.11.0") + @deprecated("use `Promise[T]()` instead", "2.11.0") // removal planned for 2.13.0 def promise[T](): Promise[T] = Promise[T]() diff --git a/src/library/scala/io/Position.scala b/src/library/scala/io/Position.scala index 011d0f17af17..0435ca95ad8e 100644 --- a/src/library/scala/io/Position.scala +++ b/src/library/scala/io/Position.scala @@ -33,7 +33,7 @@ package io * }}} * @author Burak Emir (translated from work by Matthias Zenger and others) */ -@deprecated("This class will be removed.", "2.10.0") +@deprecated("this class will be removed", "2.10.0") private[scala] abstract class Position { /** Definable behavior for overflow conditions. */ diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index e769dfb8cbe0..8e03017f0964 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -148,7 +148,7 @@ object BigDecimal { * @param mc the `MathContext` used for future computations * @return the constructed `BigDecimal` */ - @deprecated("MathContext is not applied to Doubles in valueOf. Use BigDecimal.decimal to use rounding, or java.math.BigDecimal.valueOf to avoid it.","2.11") + @deprecated("MathContext is not applied to Doubles in valueOf. Use BigDecimal.decimal to use rounding, or java.math.BigDecimal.valueOf to avoid it.", "2.11") def valueOf(d: Double, mc: MathContext): BigDecimal = apply(BigDec valueOf d, mc) /** Constructs a `BigDecimal` using the java BigDecimal static @@ -163,14 +163,14 @@ object BigDecimal { * valueOf constructor. This is unlikely to do what you want; * use `valueOf(f.toDouble)` or `decimal(f)` instead. */ - @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).","2.11") + @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).", "2.11") def valueOf(f: Float): BigDecimal = valueOf(f.toDouble) /** Constructs a `BigDecimal` using the java BigDecimal static * valueOf constructor. This is unlikely to do what you want; * use `valueOf(f.toDouble)` or `decimal(f)` instead. */ - @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).","2.11") + @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).", "2.11") def valueOf(f: Float, mc: MathContext): BigDecimal = valueOf(f.toDouble, mc) @@ -259,10 +259,10 @@ object BigDecimal { */ def apply(d: Double, mc: MathContext): BigDecimal = decimal(d, mc) - @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11") + @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11") def apply(x: Float): BigDecimal = apply(x.toDouble) - @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11") + @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11") def apply(x: Float, mc: MathContext): BigDecimal = apply(x.toDouble, mc) /** Translates a character array representation of a `BigDecimal` @@ -329,7 +329,7 @@ object BigDecimal { /** Constructs a `BigDecimal` from a `java.math.BigDecimal`. */ def apply(bd: BigDec): BigDecimal = apply(bd, defaultMathContext) - @deprecated("This method appears to round a java.math.BigDecimal but actually doesn't. Use new BigDecimal(bd, mc) instead for no rounding, or BigDecimal.decimal(bd, mc) for rounding.", "2.11") + @deprecated("This method appears to round a java.math.BigDecimal but actually doesn't. Use new BigDecimal(bd, mc) instead for no rounding, or BigDecimal.decimal(bd, mc) for rounding.", "2.11") def apply(bd: BigDec, mc: MathContext): BigDecimal = new BigDecimal(bd, mc) /** Implicit conversion from `Int` to `BigDecimal`. */ @@ -467,7 +467,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ * `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat`, depending on the intended meaning. * By default, `decimal` creation is used, so `isDecimalFloat` is probably what you want. */ - @deprecated("What constitutes validity is unclear. Use `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat` instead.", "2.11") + @deprecated("What constitutes validity is unclear. Use `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat` instead.", "2.11") def isValidFloat = { val f = toFloat !f.isInfinity && bigDecimal.compareTo(new BigDec(f.toDouble)) == 0 @@ -476,7 +476,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ * `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble`, depending on the intended meaning. * By default, `decimal` creation is used, so `isDecimalDouble` is probably what you want. */ - @deprecated("Validity has distinct meanings. Use `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble` instead.", "2.11") + @deprecated("Validity has distinct meanings. Use `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble` instead.", "2.11") def isValidDouble = { val d = toDouble !d.isInfinity && bigDecimal.compareTo(new BigDec(d)) == 0 diff --git a/src/library/scala/math/package.scala b/src/library/scala/math/package.scala index 54c81ed6134c..0e39af2febd9 100644 --- a/src/library/scala/math/package.scala +++ b/src/library/scala/math/package.scala @@ -65,9 +65,9 @@ package object math { * @return the value `logₑ(x)` where `e` is Eulers number */ def log(x: Double): Double = java.lang.Math.log(x) - + /** Returns the square root of a `double` value. - * + * * @param x the number to take the square root of * @return the value √x */ @@ -106,7 +106,7 @@ package object math { def pow(x: Double, y: Double): Double = java.lang.Math.pow(x, y) /** There is no reason to round a `Long`, but this method prevents unintended conversion to `Float` followed by rounding to `Int`. */ - @deprecated("This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value?", "2.11.0") + @deprecated("This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value?", "2.11.0") def round(x: Long): Long = x /** Returns the closest `Int` to the argument. @@ -115,7 +115,7 @@ package object math { * @return the value of the argument rounded to the nearest `Int` value. */ def round(x: Float): Int = java.lang.Math.round(x) - + /** Returns the closest `Long` to the argument. * * @param x a floating-point value to be rounded to a `Long`. diff --git a/src/library/scala/reflect/ClassManifestDeprecatedApis.scala b/src/library/scala/reflect/ClassManifestDeprecatedApis.scala index 82ec87280631..30a99340cc49 100644 --- a/src/library/scala/reflect/ClassManifestDeprecatedApis.scala +++ b/src/library/scala/reflect/ClassManifestDeprecatedApis.scala @@ -12,12 +12,12 @@ package reflect import scala.collection.mutable.{ WrappedArray, ArrayBuilder } import java.lang.{ Class => jClass } -@deprecated("Use scala.reflect.ClassTag instead", "2.10.0") +@deprecated("use scala.reflect.ClassTag instead", "2.10.0") trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { self: ClassManifest[T] => // Still in use in target test.junit.comp. - @deprecated("Use runtimeClass instead", "2.10.0") + @deprecated("use runtimeClass instead", "2.10.0") def erasure: jClass[_] = runtimeClass private def subtype(sub: jClass[_], sup: jClass[_]): Boolean = { @@ -44,7 +44,7 @@ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { * of the type represented by `that` manifest, subject to the limitations * described in the header. */ - @deprecated("Use scala.reflect.runtime.universe.TypeTag for subtype checking instead", "2.10.0") + @deprecated("use scala.reflect.runtime.universe.TypeTag for subtype checking instead", "2.10.0") def <:<(that: ClassManifest[_]): Boolean = { // All types which could conform to these types will override <:<. def cannotMatch = { @@ -78,7 +78,7 @@ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { * of the type represented by `that` manifest, subject to the limitations * described in the header. */ - @deprecated("Use scala.reflect.runtime.universe.TypeTag for subtype checking instead", "2.10.0") + @deprecated("use scala.reflect.runtime.universe.TypeTag for subtype checking instead", "2.10.0") def >:>(that: ClassManifest[_]): Boolean = that <:< this @@ -90,44 +90,44 @@ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { protected def arrayClass[T](tp: jClass[_]): jClass[Array[T]] = java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[jClass[Array[T]]] - @deprecated("Use wrap instead", "2.10.0") + @deprecated("use wrap instead", "2.10.0") def arrayManifest: ClassManifest[Array[T]] = ClassManifest.classType[Array[T]](arrayClass[T](runtimeClass), this) override def newArray(len: Int): Array[T] = java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]] - @deprecated("Use wrap.newArray instead", "2.10.0") + @deprecated("use wrap.newArray instead", "2.10.0") def newArray2(len: Int): Array[Array[T]] = java.lang.reflect.Array.newInstance(arrayClass[T](runtimeClass), len) .asInstanceOf[Array[Array[T]]] - @deprecated("Use wrap.wrap.newArray instead", "2.10.0") + @deprecated("use wrap.wrap.newArray instead", "2.10.0") def newArray3(len: Int): Array[Array[Array[T]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](runtimeClass)), len) .asInstanceOf[Array[Array[Array[T]]]] - @deprecated("Use wrap.wrap.wrap.newArray instead", "2.10.0") + @deprecated("use wrap.wrap.wrap.newArray instead", "2.10.0") def newArray4(len: Int): Array[Array[Array[Array[T]]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](runtimeClass))), len) .asInstanceOf[Array[Array[Array[Array[T]]]]] - @deprecated("Use wrap.wrap.wrap.wrap.newArray instead", "2.10.0") + @deprecated("use wrap.wrap.wrap.wrap.newArray instead", "2.10.0") def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](runtimeClass)))), len) .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]] - @deprecated("Create WrappedArray directly instead", "2.10.0") + @deprecated("create WrappedArray directly instead", "2.10.0") def newWrappedArray(len: Int): WrappedArray[T] = // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests new WrappedArray.ofRef[T with AnyRef](newArray(len).asInstanceOf[Array[T with AnyRef]]).asInstanceOf[WrappedArray[T]] - @deprecated("Use ArrayBuilder.make(this) instead", "2.10.0") + @deprecated("use ArrayBuilder.make(this) instead", "2.10.0") def newArrayBuilder(): ArrayBuilder[T] = // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests new ArrayBuilder.ofRef[T with AnyRef]()(this.asInstanceOf[ClassManifest[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]] - @deprecated("Use scala.reflect.runtime.universe.TypeTag to capture type structure instead", "2.10.0") + @deprecated("use scala.reflect.runtime.universe.TypeTag to capture type structure instead", "2.10.0") def typeArguments: List[OptManifest[_]] = List() protected def argString = diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index e0998534631e..369676c27398 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -41,7 +41,7 @@ import scala.collection.mutable.{ ArrayBuilder, WrappedArray } */ @scala.annotation.implicitNotFound(msg = "No Manifest available for ${T}.") // TODO undeprecated until Scala reflection becomes non-experimental -// @deprecated("Use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") +// @deprecated("use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") trait Manifest[T] extends ClassManifest[T] with Equals { override def typeArguments: List[Manifest[_]] = Nil @@ -63,7 +63,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals { } // TODO undeprecated until Scala reflection becomes non-experimental -// @deprecated("Use type tags and manually check the corresponding class or type instead", "2.10.0") +// @deprecated("use type tags and manually check the corresponding class or type instead", "2.10.0") @SerialVersionUID(1L) abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals { override def <:<(that: ClassManifest[_]): Boolean = diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index 509d181d87d2..88cdfb0ed495 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -25,21 +25,21 @@ package object reflect { * be wrong when variance is involved or when a subtype has a different * number of type arguments than a supertype. */ - @deprecated("Use scala.reflect.ClassTag instead", "2.10.0") + @deprecated("use scala.reflect.ClassTag instead", "2.10.0") @annotation.implicitNotFound(msg = "No ClassManifest available for ${T}.") type ClassManifest[T] = scala.reflect.ClassTag[T] /** The object `ClassManifest` defines factory methods for manifests. * It is intended for use by the compiler and should not be used in client code. */ - @deprecated("Use scala.reflect.ClassTag instead", "2.10.0") + @deprecated("use scala.reflect.ClassTag instead", "2.10.0") val ClassManifest = ClassManifestFactory /** The object `Manifest` defines factory methods for manifests. * It is intended for use by the compiler and should not be used in client code. */ // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("Use scala.reflect.ClassTag (to capture erasures), scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") + // @deprecated("use scala.reflect.ClassTag (to capture erasures), scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") val Manifest = ManifestFactory def classTag[T](implicit ctag: ClassTag[T]) = ctag diff --git a/src/library/scala/runtime/RichException.scala b/src/library/scala/runtime/RichException.scala index f01788a4e918..2863fb6d7ce2 100644 --- a/src/library/scala/runtime/RichException.scala +++ b/src/library/scala/runtime/RichException.scala @@ -11,7 +11,7 @@ package runtime import scala.compat.Platform.EOL -@deprecated("Use Throwable#getStackTrace", "2.11.0") +@deprecated("use Throwable#getStackTrace", "2.11.0") final class RichException(exc: Throwable) { def getStackTraceString = exc.getStackTrace().mkString("", EOL, EOL) } diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala index cda9d2907a6e..37d236dfe90a 100644 --- a/src/library/scala/runtime/RichInt.scala +++ b/src/library/scala/runtime/RichInt.scala @@ -36,9 +36,9 @@ final class RichInt(val self: Int) extends AnyVal with ScalaNumberProxy[Int] wit override def max(that: Int): Int = math.max(self, that) override def min(that: Int): Int = math.min(self, that) override def signum: Int = math.signum(self) - + /** There is no reason to round an `Int`, but this method is provided to avoid accidental loss of precision from a detour through `Float`. */ - @deprecated("This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value?", "2.11.0") + @deprecated("this is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value?", "2.11.0") def round: Int = self def toBinaryString: String = java.lang.Integer.toBinaryString(self) diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala index b405fcda3d5e..233ce231b4c8 100644 --- a/src/library/scala/runtime/RichLong.scala +++ b/src/library/scala/runtime/RichLong.scala @@ -32,9 +32,9 @@ final class RichLong(val self: Long) extends AnyVal with IntegralProxy[Long] { override def max(that: Long): Long = math.max(self, that) override def min(that: Long): Long = math.min(self, that) override def signum: Int = math.signum(self).toInt - + /** There is no reason to round a `Long`, but this method is provided to avoid accidental conversion to `Int` through `Float`. */ - @deprecated("This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value?", "2.11.0") + @deprecated("this is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value?", "2.11.0") def round: Long = self def toBinaryString: String = java.lang.Long.toBinaryString(self) diff --git a/src/library/scala/runtime/SeqCharSequence.scala b/src/library/scala/runtime/SeqCharSequence.scala index 293bf950dbbc..7751bf815c8a 100644 --- a/src/library/scala/runtime/SeqCharSequence.scala +++ b/src/library/scala/runtime/SeqCharSequence.scala @@ -9,7 +9,7 @@ package scala package runtime -@deprecated("Use Predef.SeqCharSequence", "2.11.0") +@deprecated("use Predef.SeqCharSequence", "2.11.0") final class SeqCharSequence(val xs: scala.collection.IndexedSeq[Char]) extends CharSequence { def length: Int = xs.length def charAt(index: Int): Char = xs(index) diff --git a/src/library/scala/runtime/StringAdd.scala b/src/library/scala/runtime/StringAdd.scala index d5b51a6e9210..37f077bcadfa 100644 --- a/src/library/scala/runtime/StringAdd.scala +++ b/src/library/scala/runtime/StringAdd.scala @@ -11,7 +11,7 @@ package runtime /** A wrapper class that adds string concatenation `+` to any value */ -@deprecated("Use Predef.StringAdd", "2.11.0") +@deprecated("use Predef.StringAdd", "2.11.0") final class StringAdd(val self: Any) extends AnyVal { def +(other: String) = String.valueOf(self) + other } diff --git a/src/library/scala/runtime/StringFormat.scala b/src/library/scala/runtime/StringFormat.scala index de32ac7e86fe..5376c3f98201 100644 --- a/src/library/scala/runtime/StringFormat.scala +++ b/src/library/scala/runtime/StringFormat.scala @@ -12,7 +12,7 @@ package runtime /** A wrapper class that adds a `formatted` operation to any value */ -@deprecated("Use Predef.StringFormat", "2.11.0") +@deprecated("use Predef.StringFormat", "2.11.0") final class StringFormat(val self: Any) extends AnyVal { /** Returns string formatted according to given `format` string. * Format strings are as for `String.format` diff --git a/src/library/scala/sys/SystemProperties.scala b/src/library/scala/sys/SystemProperties.scala index ebe94651f984..e5606f3c3b74 100644 --- a/src/library/scala/sys/SystemProperties.scala +++ b/src/library/scala/sys/SystemProperties.scala @@ -87,7 +87,7 @@ object SystemProperties { lazy val preferIPv4Stack: BooleanProp = BooleanProp.keyExists(PreferIPv4StackKey) lazy val preferIPv6Addresses: BooleanProp = BooleanProp.keyExists(PreferIPv6AddressesKey) lazy val noTraceSuppression: BooleanProp = BooleanProp.valueIsTrue(NoTraceSuppressionKey) - @deprecated("Use noTraceSuppression", "2.12.0") + @deprecated("use noTraceSuppression", "2.12.0") def noTraceSupression = noTraceSuppression } diff --git a/src/library/scala/sys/process/ProcessBuilder.scala b/src/library/scala/sys/process/ProcessBuilder.scala index ac864950011d..35f3f4d7a5f4 100644 --- a/src/library/scala/sys/process/ProcessBuilder.scala +++ b/src/library/scala/sys/process/ProcessBuilder.scala @@ -172,9 +172,9 @@ trait ProcessBuilder extends Source with Sink { * and then throw an exception. */ def lineStream: Stream[String] - + /** Deprecated (renamed). Use `lineStream` instead. */ - @deprecated("Use lineStream instead.", "2.11.0") + @deprecated("use lineStream instead", "2.11.0") def lines: Stream[String] = lineStream /** Starts the process represented by this builder. The output is returned as @@ -184,9 +184,9 @@ trait ProcessBuilder extends Source with Sink { * to termination and then throw an exception. */ def lineStream(log: ProcessLogger): Stream[String] - + /** Deprecated (renamed). Use `lineStream(log: ProcessLogger)` instead. */ - @deprecated("Use stream instead.", "2.11.0") + @deprecated("use stream instead", "2.11.0") def lines(log: ProcessLogger): Stream[String] = lineStream(log) /** Starts the process represented by this builder. The output is returned as @@ -196,9 +196,9 @@ trait ProcessBuilder extends Source with Sink { * but will not throw an exception. */ def lineStream_! : Stream[String] - + /** Deprecated (renamed). Use `lineStream_!` instead. */ - @deprecated("Use lineStream_! instead.", "2.11.0") + @deprecated("use lineStream_! instead", "2.11.0") def lines_! : Stream[String] = lineStream_! /** Starts the process represented by this builder. The output is returned as @@ -208,9 +208,9 @@ trait ProcessBuilder extends Source with Sink { * to termination but will not throw an exception. */ def lineStream_!(log: ProcessLogger): Stream[String] - + /** Deprecated (renamed). Use `lineStream_!(log: ProcessLogger)` instead. */ - @deprecated("Use stream_! instead.", "2.11.0") + @deprecated("use stream_! instead", "2.11.0") def lines_!(log: ProcessLogger): Stream[String] = lineStream_!(log) /** Starts the process represented by this builder, blocks until it exits, and diff --git a/src/library/scala/text/Document.scala b/src/library/scala/text/Document.scala index aa55ac4f0f14..0c747c99a83d 100644 --- a/src/library/scala/text/Document.scala +++ b/src/library/scala/text/Document.scala @@ -10,17 +10,17 @@ package scala.text import java.io.Writer -@deprecated("This object will be removed.", "2.11.0") +@deprecated("this object will be removed", "2.11.0") case object DocNil extends Document -@deprecated("This object will be removed.", "2.11.0") +@deprecated("this object will be removed", "2.11.0") case object DocBreak extends Document -@deprecated("This class will be removed.", "2.11.0") +@deprecated("this class will be removed", "2.11.0") case class DocText(txt: String) extends Document -@deprecated("This class will be removed.", "2.11.0") +@deprecated("this class will be removed", "2.11.0") case class DocGroup(doc: Document) extends Document -@deprecated("This class will be removed.", "2.11.0") +@deprecated("this class will be removed", "2.11.0") case class DocNest(indent: Int, doc: Document) extends Document -@deprecated("This class will be removed.", "2.11.0") +@deprecated("this class will be removed", "2.11.0") case class DocCons(hd: Document, tl: Document) extends Document /** @@ -30,7 +30,7 @@ case class DocCons(hd: Document, tl: Document) extends Document * @author Michel Schinz * @version 1.0 */ -@deprecated("This class will be removed.", "2.11.0") +@deprecated("this class will be removed", "2.11.0") abstract class Document { def ::(hd: Document): Document = DocCons(hd, this) def ::(hd: String): Document = DocCons(DocText(hd), this) @@ -103,7 +103,7 @@ abstract class Document { } } -@deprecated("This object will be removed.", "2.11.0") +@deprecated("this object will be removed", "2.11.0") object Document { /** The empty document */ def empty = DocNil diff --git a/src/library/scala/util/MurmurHash.scala b/src/library/scala/util/MurmurHash.scala index 1b6db5d6aa78..013825292e99 100644 --- a/src/library/scala/util/MurmurHash.scala +++ b/src/library/scala/util/MurmurHash.scala @@ -28,7 +28,7 @@ import scala.collection.Iterator * or can take individual hash values with append. Its own hash code is * set equal to the hash code of whatever it is hashing. */ -@deprecated("Use the object MurmurHash3 instead.", "2.10.0") +@deprecated("use the object MurmurHash3 instead", "2.10.0") class MurmurHash[@specialized(Int,Long,Float,Double) T](seed: Int) extends (T => Unit) { import MurmurHash._ @@ -81,7 +81,7 @@ class MurmurHash[@specialized(Int,Long,Float,Double) T](seed: Int) extends (T => * incorporate a new integer) to update the values. Only one method * needs to be called to finalize the hash. */ -@deprecated("Use the object MurmurHash3 instead.", "2.10.0") +@deprecated("use the object MurmurHash3 instead", "2.10.0") // NOTE: Used by SBT 0.13.0-M2 and below object MurmurHash { // Magic values used for MurmurHash's 32 bit hash. diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index bd55fb5d040a..c4a3f1effa4e 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -308,7 +308,7 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends * @param target The string to match * @return The matches */ - @deprecated("Extracting a match result from anything but a CharSequence or Match is deprecated", "2.11.0") + @deprecated("extracting a match result from anything but a CharSequence or Match is deprecated", "2.11.0") def unapplySeq(target: Any): Option[List[String]] = target match { case s: CharSequence => val m = pattern matcher s @@ -321,16 +321,16 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends // @see UnanchoredRegex protected def runMatcher(m: Matcher) = m.matches() - /** Return all non-overlapping matches of this `Regex` in the given character + /** Return all non-overlapping matches of this `Regex` in the given character * sequence as a [[scala.util.matching.Regex.MatchIterator]], * which is a special [[scala.collection.Iterator]] that returns the * matched strings but can also be queried for more data about the last match, * such as capturing groups and start position. - * + * * A `MatchIterator` can also be converted into an iterator * that returns objects of type [[scala.util.matching.Regex.Match]], * such as is normally returned by `findAllMatchIn`. - * + * * Where potential matches overlap, the first possible match is returned, * followed by the next match that follows the input consumed by the * first match: diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala index b880fad756fb..a7a564785984 100644 --- a/src/reflect/scala/reflect/api/Annotations.scala +++ b/src/reflect/scala/reflect/api/Annotations.scala @@ -55,10 +55,10 @@ trait Annotations { self: Universe => abstract class AnnotationExtractor { def apply(tree: Tree): Annotation = treeToAnnotation(tree) - @deprecated("Use `apply(tree: Tree): Annotation` instead", "2.11.0") + @deprecated("use `apply(tree: Tree): Annotation` instead", "2.11.0") def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])] } @@ -71,19 +71,19 @@ trait Annotations { self: Universe => def tree: Tree = annotationToTree(this.asInstanceOf[Annotation]) /** The type of the annotation. */ - @deprecated("Use `tree.tpe` instead", "2.11.0") + @deprecated("use `tree.tpe` instead", "2.11.0") def tpe: Type /** Payload of the Scala annotation: a list of abstract syntax trees that represent the argument. * Empty for Java annotations. */ - @deprecated("Use `tree.children.tail` instead", "2.11.0") + @deprecated("use `tree.children.tail` instead", "2.11.0") def scalaArgs: List[Tree] /** Payload of the Java annotation: a list of name-value pairs. * Empty for Scala annotations. */ - @deprecated("Use `tree.children.tail` instead", "2.11.0") + @deprecated("use `tree.children.tail` instead", "2.11.0") def javaArgs: ListMap[Name, JavaArgument] } @@ -94,37 +94,37 @@ trait Annotations { self: Universe => * @template * @group Annotations */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") type JavaArgument >: Null <: AnyRef with JavaArgumentApi /** Has no special methods. Is here to provides erased identity for `CompoundType`. * @group API */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") trait JavaArgumentApi - /** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")` + /** A literal argument to a Java annotation as `"use X instead"` in `@Deprecated("use X instead")` * @template * @group Annotations */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") type LiteralArgument >: Null <: LiteralArgumentApi with JavaArgument /** The constructor/extractor for `LiteralArgument` instances. * @group Extractors */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") val LiteralArgument: LiteralArgumentExtractor /** An extractor class to create and pattern match with syntax `LiteralArgument(value)` * where `value` is the constant argument. * @group Extractors */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") abstract class LiteralArgumentExtractor { - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def apply(value: Constant): LiteralArgument - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def unapply(arg: LiteralArgument): Option[Constant] } @@ -132,10 +132,10 @@ trait Annotations { self: Universe => * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page. * @group API */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") trait LiteralArgumentApi { /** The underlying compile-time constant value. */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def value: Constant } @@ -143,24 +143,24 @@ trait Annotations { self: Universe => * @template * @group Annotations */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") type ArrayArgument >: Null <: ArrayArgumentApi with JavaArgument /** The constructor/extractor for `ArrayArgument` instances. * @group Extractors */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") val ArrayArgument: ArrayArgumentExtractor /** An extractor class to create and pattern match with syntax `ArrayArgument(args)` * where `args` is the argument array. * @group Extractors */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") abstract class ArrayArgumentExtractor { - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def apply(args: Array[JavaArgument]): ArrayArgument - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def unapply(arg: ArrayArgument): Option[Array[JavaArgument]] } @@ -168,10 +168,10 @@ trait Annotations { self: Universe => * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page. * @group API */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") trait ArrayArgumentApi { /** The underlying array of Java annotation arguments. */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def args: Array[JavaArgument] } @@ -179,24 +179,24 @@ trait Annotations { self: Universe => * @template * @group Annotations */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") type NestedArgument >: Null <: NestedArgumentApi with JavaArgument /** The constructor/extractor for `NestedArgument` instances. * @group Extractors */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") val NestedArgument: NestedArgumentExtractor /** An extractor class to create and pattern match with syntax `NestedArgument(annotation)` * where `annotation` is the nested annotation. * @group Extractors */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") abstract class NestedArgumentExtractor { - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def apply(annotation: Annotation): NestedArgument - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def unapply(arg: NestedArgument): Option[Annotation] } @@ -204,10 +204,10 @@ trait Annotations { self: Universe => * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page. * @group API */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") trait NestedArgumentApi { /** The underlying nested annotation. */ - @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + @deprecated("use `Annotation.tree` to inspect annotation arguments", "2.11.0") def annotation: Annotation } } diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index 2d5d1d5d6bc0..14852c0231ce 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -173,7 +173,7 @@ trait FlagSets { self: Universe => * - the enum's class * - enum constants **/ - @deprecated("Use `isJavaEnum` on the corresponding symbol instead.", since = "2.11.8") + @deprecated("use `isJavaEnum` on the corresponding symbol instead", since = "2.11.8") val ENUM: FlagSet /** Flag indicating that tree represents a parameter of the primary constructor of some class diff --git a/src/reflect/scala/reflect/api/Internals.scala b/src/reflect/scala/reflect/api/Internals.scala index 1457fdc13302..9b7112f01178 100644 --- a/src/reflect/scala/reflect/api/Internals.scala +++ b/src/reflect/scala/reflect/api/Internals.scala @@ -841,10 +841,10 @@ trait Internals { self: Universe => } } - @deprecated("Use `internal.reificationSupport` instead", "2.11.0") + @deprecated("use `internal.reificationSupport` instead", "2.11.0") val build: ReificationSupportApi - @deprecated("Use `internal.ReificationSupportApi` instead", "2.11.0") + @deprecated("use `internal.ReificationSupportApi` instead", "2.11.0") type BuildApi = ReificationSupportApi /** This trait provides support for importers, a facility to migrate reflection artifacts between universes. @@ -934,7 +934,7 @@ trait Internals { self: Universe => def importPosition(pos: from.Position): Position } - @deprecated("Use `internal.createImporter` instead", "2.11.0") + @deprecated("use `internal.createImporter` instead", "2.11.0") def mkImporter(from0: Universe): Importer { val from: from0.type } = internal.createImporter(from0) /** Marks underlying reference to id as boxed. @@ -1078,71 +1078,71 @@ trait Internals { self: Universe => implicit val token = new CompatToken /** @see [[InternalApi.typeTagToManifest]] */ - @deprecated("Use `internal.typeTagToManifest` instead", "2.11.0") + @deprecated("use `internal.typeTagToManifest` instead", "2.11.0") def typeTagToManifest[T: ClassTag](mirror: Any, tag: Universe#TypeTag[T]): Manifest[T] = internal.typeTagToManifest(mirror, tag) /** @see [[InternalApi.manifestToTypeTag]] */ - @deprecated("Use `internal.manifestToTypeTag` instead", "2.11.0") + @deprecated("use `internal.manifestToTypeTag` instead", "2.11.0") def manifestToTypeTag[T](mirror: Any, manifest: Manifest[T]): Universe#TypeTag[T] = internal.manifestToTypeTag(mirror, manifest) /** @see [[InternalApi.newScopeWith]] */ - @deprecated("Use `internal.newScopeWith` instead", "2.11.0") + @deprecated("use `internal.newScopeWith` instead", "2.11.0") def newScopeWith(elems: Symbol*): Scope = internal.newScopeWith(elems: _*) /** Scala 2.10 compatibility enrichments for BuildApi. */ implicit class CompatibleBuildApi(api: BuildApi) { /** @see [[BuildApi.setInfo]] */ - @deprecated("Use `internal.reificationSupport.setInfo` instead", "2.11.0") + @deprecated("use `internal.reificationSupport.setInfo` instead", "2.11.0") def setTypeSignature[S <: Symbol](sym: S, tpe: Type): S = internal.reificationSupport.setInfo(sym, tpe) /** @see [[BuildApi.FlagsRepr]] */ - @deprecated("Use `internal.reificationSupport.FlagsRepr` instead", "2.11.0") + @deprecated("use `internal.reificationSupport.FlagsRepr` instead", "2.11.0") def flagsFromBits(bits: Long): FlagSet = internal.reificationSupport.FlagsRepr(bits) /** @see [[BuildApi.noSelfType]] */ - @deprecated("Use `noSelfType` instead", "2.11.0") + @deprecated("use `noSelfType` instead", "2.11.0") def emptyValDef: ValDef = noSelfType /** @see [[BuildApi.mkThis]] */ - @deprecated("Use `internal.reificationSupport.mkThis` instead", "2.11.0") + @deprecated("use `internal.reificationSupport.mkThis` instead", "2.11.0") def This(sym: Symbol): Tree = internal.reificationSupport.mkThis(sym) /** @see [[BuildApi.mkSelect]] */ - @deprecated("Use `internal.reificationSupport.mkSelect` instead", "2.11.0") + @deprecated("use `internal.reificationSupport.mkSelect` instead", "2.11.0") def Select(qualifier: Tree, sym: Symbol): Select = internal.reificationSupport.mkSelect(qualifier, sym) /** @see [[BuildApi.mkIdent]] */ - @deprecated("Use `internal.reificationSupport.mkIdent` instead", "2.11.0") + @deprecated("use `internal.reificationSupport.mkIdent` instead", "2.11.0") def Ident(sym: Symbol): Ident = internal.reificationSupport.mkIdent(sym) /** @see [[BuildApi.mkTypeTree]] */ - @deprecated("Use `internal.reificationSupport.mkTypeTree` instead", "2.11.0") + @deprecated("use `internal.reificationSupport.mkTypeTree` instead", "2.11.0") def TypeTree(tp: Type): TypeTree = internal.reificationSupport.mkTypeTree(tp) } /** Scala 2.10 compatibility enrichments for Tree. */ implicit class CompatibleTree(tree: Tree) { /** @see [[InternalApi.freeTerms]] */ - @deprecated("Use `internal.freeTerms` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.freeTerms` instead or import `internal.decorators._` for infix syntax", "2.11.0") def freeTerms: List[FreeTermSymbol] = internal.freeTerms(tree) /** @see [[InternalApi.freeTypes]] */ - @deprecated("Use `internal.freeTerms` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.freeTerms` instead or import `internal.decorators._` for infix syntax", "2.11.0") def freeTypes: List[FreeTypeSymbol] = internal.freeTypes(tree) /** @see [[InternalApi.substituteSymbols]] */ - @deprecated("Use `internal.substituteSymbols` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.substituteSymbols` instead or import `internal.decorators._` for infix syntax", "2.11.0") def substituteSymbols(from: List[Symbol], to: List[Symbol]): Tree = internal.substituteSymbols(tree, from, to) /** @see [[InternalApi.substituteTypes]] */ - @deprecated("Use `internal.substituteTypes` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.substituteTypes` instead or import `internal.decorators._` for infix syntax", "2.11.0") def substituteTypes(from: List[Symbol], to: List[Type]): Tree = internal.substituteTypes(tree, from, to) /** @see [[InternalApi.substituteThis]] */ - @deprecated("Use `internal.substituteThis` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.substituteThis` instead or import `internal.decorators._` for infix syntax", "2.11.0") def substituteThis(clazz: Symbol, to: Tree): Tree = internal.substituteThis(tree, clazz, to) } @@ -1155,84 +1155,84 @@ trait Internals { self: Universe => def isOverride: Boolean = symbol.asInstanceOf[scala.reflect.internal.Symbols#Symbol].isOverride /** @see [[InternalApi.isFreeTerm]] */ - @deprecated("Use `internal.isFreeTerm` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.isFreeTerm` instead or import `internal.decorators._` for infix syntax", "2.11.0") def isFreeTerm: Boolean = internal.isFreeTerm(symbol) /** @see [[InternalApi.asFreeTerm]] */ - @deprecated("Use `internal.asFreeTerm` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.asFreeTerm` instead or import `internal.decorators._` for infix syntax", "2.11.0") def asFreeTerm: FreeTermSymbol = internal.asFreeTerm(symbol) /** @see [[InternalApi.isFreeType]] */ - @deprecated("Use `internal.isFreeType` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.isFreeType` instead or import `internal.decorators._` for infix syntax", "2.11.0") def isFreeType: Boolean = internal.isFreeType(symbol) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.asFreeType` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.asFreeType` instead or import `internal.decorators._` for infix syntax", "2.11.0") def asFreeType: FreeTypeSymbol = internal.asFreeType(symbol) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.newTermSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.newTermSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol = internal.newTermSymbol(symbol, name, pos, flags) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.newModuleAndClassSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.newModuleAndClassSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol) = internal.newModuleAndClassSymbol(symbol, name, pos, flags) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.newMethodSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.newMethodSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): MethodSymbol = internal.newMethodSymbol(symbol, name, pos, flags) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.newTypeSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.newTypeSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TypeSymbol = internal.newTypeSymbol(symbol, name, pos, flags) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.newClassSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.newClassSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): ClassSymbol = internal.newClassSymbol(symbol, name, pos, flags) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.isErroneous` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.isErroneous` instead or import `internal.decorators._` for infix syntax", "2.11.0") def isErroneous: Boolean = internal.isErroneous(symbol) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.isSkolem` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.isSkolem` instead or import `internal.decorators._` for infix syntax", "2.11.0") def isSkolem: Boolean = internal.isSkolem(symbol) /** @see [[InternalApi.asFreeType]] */ - @deprecated("Use `internal.deSkolemize` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.deSkolemize` instead or import `internal.decorators._` for infix syntax", "2.11.0") def deSkolemize: Symbol = internal.deSkolemize(symbol) } /** @see [[InternalApi.singleType]] */ - @deprecated("Use `internal.singleType` instead", "2.11.0") + @deprecated("use `internal.singleType` instead", "2.11.0") def singleType(pre: Type, sym: Symbol): Type = internal.singleType(pre, sym) /** @see [[InternalApi.refinedType]] */ - @deprecated("Use `internal.refinedType` instead", "2.11.0") + @deprecated("use `internal.refinedType` instead", "2.11.0") def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos: Position): Type = internal.refinedType(parents, owner, decls, pos) /** @see [[InternalApi.refinedType]] */ - @deprecated("Use `internal.refinedType` instead", "2.11.0") + @deprecated("use `internal.refinedType` instead", "2.11.0") def refinedType(parents: List[Type], owner: Symbol): Type = internal.refinedType(parents, owner) /** @see [[InternalApi.typeRef]] */ - @deprecated("Use `internal.typeRef` instead", "2.11.0") + @deprecated("use `internal.typeRef` instead", "2.11.0") def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = internal.typeRef(pre, sym, args) /** @see [[InternalApi.intersectionType]] */ - @deprecated("Use `internal.intersectionType` instead", "2.11.0") + @deprecated("use `internal.intersectionType` instead", "2.11.0") def intersectionType(tps: List[Type]): Type = internal.intersectionType(tps) /** @see [[InternalApi.intersectionType]] */ - @deprecated("Use `internal.intersectionType` instead", "2.11.0") + @deprecated("use `internal.intersectionType` instead", "2.11.0") def intersectionType(tps: List[Type], owner: Symbol): Type = internal.intersectionType(tps, owner) /** @see [[InternalApi.polyType]] */ - @deprecated("Use `internal.polyType` instead", "2.11.0") + @deprecated("use `internal.polyType` instead", "2.11.0") def polyType(tparams: List[Symbol], tpe: Type): Type = internal.polyType(tparams, tpe) /** @see [[InternalApi.existentialAbstraction]] */ - @deprecated("Use `internal.existentialAbstraction` instead", "2.11.0") + @deprecated("use `internal.existentialAbstraction` instead", "2.11.0") def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type = internal.existentialAbstraction(tparams, tpe0) } } diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala index cc0122528707..35009d7f591a 100644 --- a/src/reflect/scala/reflect/api/Names.scala +++ b/src/reflect/scala/reflect/api/Names.scala @@ -33,14 +33,14 @@ trait Names { * Enables an alternative notation `"map": TermName` as opposed to `TermName("map")`. * @group Names */ - @deprecated("Use explicit `TermName(s)` instead", "2.11.0") + @deprecated("use explicit `TermName(s)` instead", "2.11.0") implicit def stringToTermName(s: String): TermName = TermName(s) /** An implicit conversion from String to TypeName. * Enables an alternative notation `"List": TypeName` as opposed to `TypeName("List")`. * @group Names */ - @deprecated("Use explicit `TypeName(s)` instead", "2.11.0") + @deprecated("use explicit `TypeName(s)` instead", "2.11.0") implicit def stringToTypeName(s: String): TypeName = TypeName(s) /** The abstract type of names. @@ -87,13 +87,13 @@ trait Names { /** Replaces all occurrences of \$op_names in this name by corresponding operator symbols. * Example: `foo_\$plus\$eq` becomes `foo_+=` */ - @deprecated("Use `decodedName.toString` instead", "2.11.0") + @deprecated("use `decodedName.toString` instead", "2.11.0") def decoded: String /** Replaces all occurrences of operator symbols in this name by corresponding \$op_names. * Example: `foo_+=` becomes `foo_\$plus\$eq`. */ - @deprecated("Use `encodedName.toString` instead", "2.11.0") + @deprecated("use `encodedName.toString` instead", "2.11.0") def encoded: String /** The decoded name, still represented as a name. @@ -108,13 +108,13 @@ trait Names { /** Create a new term name. * @group Names */ - @deprecated("Use TermName instead", "2.11.0") + @deprecated("use TermName instead", "2.11.0") def newTermName(s: String): TermName /** Creates a new type name. * @group Names */ - @deprecated("Use TypeName instead", "2.11.0") + @deprecated("use TypeName instead", "2.11.0") def newTypeName(s: String): TypeName /** The constructor/extractor for `TermName` instances. diff --git a/src/reflect/scala/reflect/api/Position.scala b/src/reflect/scala/reflect/api/Position.scala index 9d1b7c3812a0..2e02d4a26f2f 100644 --- a/src/reflect/scala/reflect/api/Position.scala +++ b/src/reflect/scala/reflect/api/Position.scala @@ -130,78 +130,78 @@ trait Position extends Attachments { * If isDefined is true, offset and source are both defined. * @group Common */ - @deprecated("Removed from the public API", "2.11.0") def isDefined: Boolean + @deprecated("removed from the public API", "2.11.0") def isDefined: Boolean /** The point (where the ^ is) of the position, or else `default` if undefined. * @group Common */ - @deprecated("Removed from the public API", "2.11.0") def pointOrElse(default: Int): Int + @deprecated("removed from the public API", "2.11.0") def pointOrElse(default: Int): Int /** The start of the position's range, or point if not a range position. */ - @deprecated("Removed from the public API", "2.11.0") def startOrPoint: Int + @deprecated("removed from the public API", "2.11.0") def startOrPoint: Int /** The end of the position's range, or point if not a range position. */ - @deprecated("Removed from the public API", "2.11.0") def endOrPoint: Int + @deprecated("removed from the public API", "2.11.0") def endOrPoint: Int /** If this is a range, the union with the other range, with the point of this position. * Otherwise, this position */ - @deprecated("Removed from the public API", "2.11.0") def union(pos: Pos): Pos + @deprecated("removed from the public API", "2.11.0") def union(pos: Pos): Pos /** If this is a range position, the offset position of its start. * Otherwise the position itself */ - @deprecated("Removed from the public API", "2.11.0") def focusStart: Pos + @deprecated("removed from the public API", "2.11.0") def focusStart: Pos /** If this is a range position, the offset position of its end. * Otherwise the position itself */ - @deprecated("Removed from the public API", "2.11.0") def focusEnd: Pos + @deprecated("removed from the public API", "2.11.0") def focusEnd: Pos /** Does this position include the given position `pos`? * This holds if `this` is a range position and its range [start..end] * is the same or covers the range of the given position, which may or may not be a range position. */ - @deprecated("Removed from the public API", "2.11.0") def includes(pos: Pos): Boolean + @deprecated("removed from the public API", "2.11.0") def includes(pos: Pos): Boolean /** Does this position properly include the given position `pos` ("properly" meaning their * ranges are not the same)? */ - @deprecated("Removed from the public API", "2.11.0") def properlyIncludes(pos: Pos): Boolean + @deprecated("removed from the public API", "2.11.0") def properlyIncludes(pos: Pos): Boolean /** Does this position precede that position? * This holds if both positions are defined and the end point of this position * is not larger than the start point of the given position. */ - @deprecated("Removed from the public API", "2.11.0") def precedes(pos: Pos): Boolean + @deprecated("removed from the public API", "2.11.0") def precedes(pos: Pos): Boolean /** Does this position properly precede the given position `pos` ("properly" meaning their ranges * do not share a common point). */ - @deprecated("Removed from the public API", "2.11.0") def properlyPrecedes(pos: Pos): Boolean + @deprecated("removed from the public API", "2.11.0") def properlyPrecedes(pos: Pos): Boolean /** Does this position overlap with that position? * This holds if both positions are ranges and there is an interval of * non-zero length that is shared by both position ranges. */ - @deprecated("Removed from the public API", "2.11.0") def overlaps(pos: Pos): Boolean + @deprecated("removed from the public API", "2.11.0") def overlaps(pos: Pos): Boolean /** Does this position cover the same range as that position? * Holds only if both position are ranges */ - @deprecated("Removed from the public API", "2.11.0") def sameRange(pos: Pos): Boolean + @deprecated("removed from the public API", "2.11.0") def sameRange(pos: Pos): Boolean /** Convert this to a position around `point` that spans a single source line */ - @deprecated("Removed from the public API", "2.11.0") def toSingleLine: Pos + @deprecated("removed from the public API", "2.11.0") def toSingleLine: Pos /** The content of the line this Position refers to. * @group Common */ - @deprecated("Removed from the public API", "2.11.0") def lineContent: String + @deprecated("removed from the public API", "2.11.0") def lineContent: String /** Show a textual representation of the position. */ - @deprecated("Use `universe.show(position)` instead", "2.11.0") def show: String + @deprecated("use `universe.show(position)` instead", "2.11.0") def show: String } diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala index 19bdfcae593b..38667ae15300 100644 --- a/src/reflect/scala/reflect/api/StandardNames.scala +++ b/src/reflect/scala/reflect/api/StandardNames.scala @@ -29,7 +29,7 @@ trait StandardNames { self: Universe => /** @see [[termNames]] */ - @deprecated("Use `termNames` instead", "2.11.0") + @deprecated("use `termNames` instead", "2.11.0") val nme: TermNamesApi /** A value containing all [[TermNamesApi standard term names]]. @@ -38,7 +38,7 @@ trait StandardNames { val termNames: TermNamesApi /** @see [[typeNames]] */ - @deprecated("Use `typeNames` instead", "2.11.0") + @deprecated("use `typeNames` instead", "2.11.0") val tpnme: TypeNamesApi /** A value containing all [[TypeNamesApi standard type names]]. diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index b9fb323a4ce7..79bf9e969ca9 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -280,7 +280,7 @@ trait Symbols { self: Universe => * * @group Basics */ - @deprecated("Use `pos.source.file` instead", "2.11.0") + @deprecated("use `pos.source.file` instead", "2.11.0") def associatedFile: scala.reflect.io.AbstractFile /** A list of annotations attached to this Symbol. @@ -298,7 +298,7 @@ trait Symbols { self: Universe => * * @group Basics */ - @deprecated("Use `companion` instead, but beware of possible changes in behavior", "2.11.0") + @deprecated("use `companion` instead, but beware of possible changes in behavior", "2.11.0") def companionSymbol: Symbol /** For a class: its companion object if exists. @@ -333,7 +333,7 @@ trait Symbols { self: Universe => def info: Type /** @see [[overrides]] */ - @deprecated("Use `overrides` instead", "2.11.0") + @deprecated("use `overrides` instead", "2.11.0") def allOverriddenSymbols: List[Symbol] /** Returns all symbols overridden by this symbol. @@ -726,7 +726,7 @@ trait Symbols { self: Universe => * * @group Type */ - @deprecated("Use isAbstract instead", "2.11.0") + @deprecated("use isAbstract instead", "2.11.0") def isAbstractType : Boolean /** Does this symbol represent an existentially bound type? @@ -767,7 +767,7 @@ trait Symbols { self: Universe => /** @see [[paramLists]] * * The name ending with "ss" indicates that the result type is a list of lists. */ - @deprecated("Use `paramLists` instead", "2.11.0") + @deprecated("use `paramLists` instead", "2.11.0") def paramss: List[List[Symbol]] /** All parameter lists of the method. @@ -864,7 +864,7 @@ trait Symbols { self: Universe => * * @group Class */ - @deprecated("Use isAbstract instead", "2.11.0") + @deprecated("use isAbstract instead", "2.11.0") def isAbstractClass: Boolean /** Does this symbol represent a case class? diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index a43195d9b630..a2d11cc60e27 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -388,7 +388,7 @@ trait Trees { self: Universe => def unapply(classDef: ClassDef): Option[(Modifiers, TypeName, List[TypeDef], Template)] /** @see [[InternalApi.classDef]] */ - @deprecated("Use `internal.classDef` instead", "2.11.0") + @deprecated("use `internal.classDef` instead", "2.11.0") def apply(sym: Symbol, impl: Template)(implicit token: CompatToken): ClassDef = internal.classDef(sym, impl) } @@ -437,7 +437,7 @@ trait Trees { self: Universe => def unapply(moduleDef: ModuleDef): Option[(Modifiers, TermName, Template)] /** @see [[InternalApi.moduleDef]] */ - @deprecated("Use `internal.moduleDef` instead", "2.11.0") + @deprecated("use `internal.moduleDef` instead", "2.11.0") def apply(sym: Symbol, impl: Template)(implicit token: CompatToken): ModuleDef = internal.moduleDef(sym, impl) } @@ -517,11 +517,11 @@ trait Trees { self: Universe => def unapply(valDef: ValDef): Option[(Modifiers, TermName, Tree, Tree)] /** @see [[InternalApi.valDef]] */ - @deprecated("Use `internal.valDef` instead", "2.11.0") + @deprecated("use `internal.valDef` instead", "2.11.0") def apply(sym: Symbol, rhs: Tree)(implicit token: CompatToken): ValDef = internal.valDef(sym, rhs) /** @see [[InternalApi.valDef]] */ - @deprecated("Use `internal.valDef` instead", "2.11.0") + @deprecated("use `internal.valDef` instead", "2.11.0") def apply(sym: Symbol)(implicit token: CompatToken): ValDef = internal.valDef(sym) } @@ -568,23 +568,23 @@ trait Trees { self: Universe => def unapply(defDef: DefDef): Option[(Modifiers, TermName, List[TypeDef], List[List[ValDef]], Tree, Tree)] /** @see [[InternalApi.defDef]] */ - @deprecated("Use `internal.defDef` instead", "2.11.0") + @deprecated("use `internal.defDef` instead", "2.11.0") def apply(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree)(implicit token: CompatToken): DefDef = internal.defDef(sym, mods, vparamss, rhs) /** @see [[InternalApi.defDef]] */ - @deprecated("Use `internal.defDef` instead", "2.11.0") + @deprecated("use `internal.defDef` instead", "2.11.0") def apply(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree)(implicit token: CompatToken): DefDef = internal.defDef(sym, vparamss, rhs) /** @see [[InternalApi.defDef]] */ - @deprecated("Use `internal.defDef` instead", "2.11.0") + @deprecated("use `internal.defDef` instead", "2.11.0") def apply(sym: Symbol, mods: Modifiers, rhs: Tree)(implicit token: CompatToken): DefDef = internal.defDef(sym, mods, rhs) /** @see [[InternalApi.defDef]] */ - @deprecated("Use `internal.defDef` instead", "2.11.0") + @deprecated("use `internal.defDef` instead", "2.11.0") def apply(sym: Symbol, rhs: Tree)(implicit token: CompatToken): DefDef = internal.defDef(sym, rhs) /** @see [[InternalApi.defDef]] */ - @deprecated("Use `internal.defDef` instead", "2.11.0") + @deprecated("use `internal.defDef` instead", "2.11.0") def apply(sym: Symbol, rhs: List[List[Symbol]] => Tree)(implicit token: CompatToken): DefDef = internal.defDef(sym, rhs) } @@ -640,11 +640,11 @@ trait Trees { self: Universe => def unapply(typeDef: TypeDef): Option[(Modifiers, TypeName, List[TypeDef], Tree)] /** @see [[InternalApi.typeDef]] */ - @deprecated("Use `internal.typeDef` instead", "2.11.0") + @deprecated("use `internal.typeDef` instead", "2.11.0") def apply(sym: Symbol, rhs: Tree)(implicit token: CompatToken): TypeDef = internal.typeDef(sym, rhs) /** @see [[InternalApi.typeDef]] */ - @deprecated("Use `internal.typeDef` instead", "2.11.0") + @deprecated("use `internal.typeDef` instead", "2.11.0") def apply(sym: Symbol)(implicit token: CompatToken): TypeDef = internal.typeDef(sym) } @@ -708,7 +708,7 @@ trait Trees { self: Universe => def unapply(labelDef: LabelDef): Option[(TermName, List[Ident], Tree)] /** @see [[InternalApi.labelDef]] */ - @deprecated("Use `internal.labelDef` instead", "2.11.0") + @deprecated("use `internal.labelDef` instead", "2.11.0") def apply(sym: Symbol, params: List[Symbol], rhs: Tree)(implicit token: CompatToken): LabelDef = internal.labelDef(sym, params, rhs) } @@ -2104,7 +2104,7 @@ trait Trees { self: Universe => */ val noSelfType: ValDef - @deprecated("Use `noSelfType` instead", "2.11.0") + @deprecated("use `noSelfType` instead", "2.11.0") val emptyValDef: ValDef /** An empty superclass constructor call corresponding to: @@ -2122,68 +2122,68 @@ trait Trees { self: Universe => * Flattens directly nested blocks. * @group Factories */ - @deprecated("Use q\"{..$stats}\" instead. Flatten directly nested blocks manually if needed", "2.10.1") + @deprecated("use q\"{..$stats}\" instead. Flatten directly nested blocks manually if needed", "2.10.1") def Block(stats: Tree*): Block /** A factory method for `CaseDef` nodes. * @group Factories */ - @deprecated("Use cq\"$pat => $body\" instead", "2.10.1") + @deprecated("use cq\"$pat => $body\" instead", "2.10.1") def CaseDef(pat: Tree, body: Tree): CaseDef /** A factory method for `Bind` nodes. * @group Factories */ - @deprecated("Use the canonical Bind constructor to create a bind and then initialize its symbol manually", "2.10.1") + @deprecated("use the canonical Bind constructor to create a bind and then initialize its symbol manually", "2.10.1") def Bind(sym: Symbol, body: Tree): Bind /** A factory method for `Try` nodes. * @group Factories */ - @deprecated("Convert cases into casedefs and use q\"try $body catch { case ..$newcases }\" instead", "2.10.1") + @deprecated("convert cases into casedefs and use q\"try $body catch { case ..$newcases }\" instead", "2.10.1") def Try(body: Tree, cases: (Tree, Tree)*): Try /** A factory method for `Throw` nodes. * @group Factories */ - @deprecated("Use q\"throw new $tpe(..$args)\" instead", "2.10.1") + @deprecated("use q\"throw new $tpe(..$args)\" instead", "2.10.1") def Throw(tpe: Type, args: Tree*): Throw /** Factory method for object creation `new tpt(args_1)...(args_n)` * A `New(t, as)` is expanded to: `(new t).(as)` * @group Factories */ - @deprecated("Use q\"new $tpt(...$argss)\" instead", "2.10.1") + @deprecated("use q\"new $tpt(...$argss)\" instead", "2.10.1") def New(tpt: Tree, argss: List[List[Tree]]): Tree /** 0-1 argument list new, based on a type. * @group Factories */ - @deprecated("Use q\"new $tpe(..$args)\" instead", "2.10.1") + @deprecated("use q\"new $tpe(..$args)\" instead", "2.10.1") def New(tpe: Type, args: Tree*): Tree /** 0-1 argument list new, based on a symbol. * @group Factories */ - @deprecated("Use q\"new ${sym.toType}(..$args)\" instead", "2.10.1") + @deprecated("use q\"new ${sym.toType}(..$args)\" instead", "2.10.1") def New(sym: Symbol, args: Tree*): Tree /** A factory method for `Apply` nodes. * @group Factories */ - @deprecated("Use q\"$sym(..$args)\" instead", "2.10.1") + @deprecated("use q\"$sym(..$args)\" instead", "2.10.1") def Apply(sym: Symbol, args: Tree*): Tree /** 0-1 argument list new, based on a type tree. * @group Factories */ - @deprecated("Use q\"new $tpt(..$args)\" instead", "2.10.1") + @deprecated("use q\"new $tpt(..$args)\" instead", "2.10.1") def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree /** A factory method for `Super` nodes. * @group Factories */ - @deprecated("Use q\"$sym.super[$mix].x\".qualifier instead", "2.10.1") + @deprecated("use q\"$sym.super[$mix].x\".qualifier instead", "2.10.1") def Super(sym: Symbol, mix: TypeName): Tree /** A factory method for `This` nodes. @@ -2195,7 +2195,7 @@ trait Trees { self: Universe => * The string `name` argument is assumed to represent a [[scala.reflect.api.Names#TermName `TermName`]]. * @group Factories */ - @deprecated("Use Select(tree, TermName(name)) instead", "2.10.1") + @deprecated("use Select(tree, TermName(name)) instead", "2.10.1") def Select(qualifier: Tree, name: String): Select /** A factory method for `Select` nodes. @@ -2206,7 +2206,7 @@ trait Trees { self: Universe => /** A factory method for `Ident` nodes. * @group Factories */ - @deprecated("Use Ident(TermName(name)) instead", "2.10.1") + @deprecated("use Ident(TermName(name)) instead", "2.10.1") def Ident(name: String): Ident /** A factory method for `Ident` nodes. @@ -2653,7 +2653,7 @@ trait Trees { self: Universe => */ val Modifiers: ModifiersExtractor - @deprecated("Use ModifiersExtractor instead", "2.11.0") + @deprecated("use ModifiersExtractor instead", "2.11.0") type ModifiersCreator = ModifiersExtractor /** An extractor class to create and pattern match with syntax `Modifiers(flags, privateWithin, annotations)`. diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala index f9b49f173071..ff61ae1901a4 100644 --- a/src/reflect/scala/reflect/api/Types.scala +++ b/src/reflect/scala/reflect/api/Types.scala @@ -95,7 +95,7 @@ trait Types { def typeSymbol: Symbol /** @see [[decl]] */ - @deprecated("Use `decl` instead", "2.11.0") + @deprecated("use `decl` instead", "2.11.0") def declaration(name: Name): Symbol /** The defined or declared members with name `name` in this type; @@ -105,7 +105,7 @@ trait Types { def decl(name: Name): Symbol /** @see [[decls]] */ - @deprecated("Use `decls` instead", "2.11.0") + @deprecated("use `decls` instead", "2.11.0") def declarations: MemberScope /** A `Scope` containing directly declared members of this type. @@ -150,7 +150,7 @@ trait Types { * TypeRef(pre, , List()) is replaced by * PolyType(X, TypeRef(pre, , List(X))) */ - @deprecated("Use `dealias` or `etaExpand` instead", "2.11.0") + @deprecated("use `dealias` or `etaExpand` instead", "2.11.0") def normalize: Type /** Converts higher-kinded TypeRefs to PolyTypes. @@ -263,7 +263,7 @@ trait Types { def typeArgs: List[Type] /** @see [[paramLists]] */ - @deprecated("Use `paramLists` instead", "2.11.0") + @deprecated("use `paramLists` instead", "2.11.0") def paramss: List[List[Symbol]] /** For a method or poly type, a list of its value parameter sections, @@ -430,7 +430,7 @@ trait Types { def unapply(tpe: ThisType): Option[Symbol] /** @see [[InternalApi.thisType]] */ - @deprecated("Use `internal.thisType` instead", "2.11.0") + @deprecated("use `internal.thisType` instead", "2.11.0") def apply(sym: Symbol)(implicit token: CompatToken): Type = internal.thisType(sym) } @@ -469,7 +469,7 @@ trait Types { def unapply(tpe: SingleType): Option[(Type, Symbol)] /** @see [[InternalApi.singleType]] */ - @deprecated("Use `ClassSymbol.thisPrefix` or `internal.singleType` instead", "2.11.0") + @deprecated("use `ClassSymbol.thisPrefix` or `internal.singleType` instead", "2.11.0") def apply(pre: Type, sym: Symbol)(implicit token: CompatToken): Type = internal.singleType(pre, sym) } @@ -509,7 +509,7 @@ trait Types { def unapply(tpe: SuperType): Option[(Type, Type)] /** @see [[InternalApi.superType]] */ - @deprecated("Use `ClassSymbol.superPrefix` or `internal.superType` instead", "2.11.0") + @deprecated("use `ClassSymbol.superPrefix` or `internal.superType` instead", "2.11.0") def apply(thistpe: Type, supertpe: Type)(implicit token: CompatToken): Type = internal.superType(thistpe, supertpe) } @@ -552,7 +552,7 @@ trait Types { def unapply(tpe: ConstantType): Option[Constant] /** @see [[InternalApi.constantType]] */ - @deprecated("Use `value.tpe` or `internal.constantType` instead", "2.11.0") + @deprecated("use `value.tpe` or `internal.constantType` instead", "2.11.0") def apply(value: Constant)(implicit token: CompatToken): ConstantType = internal.constantType(value) } @@ -595,7 +595,7 @@ trait Types { def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] /** @see [[InternalApi.typeRef]] */ - @deprecated("Use `internal.typeRef` instead", "2.11.0") + @deprecated("use `internal.typeRef` instead", "2.11.0") def apply(pre: Type, sym: Symbol, args: List[Type])(implicit token: CompatToken): Type = internal.typeRef(pre, sym, args) } @@ -655,11 +655,11 @@ trait Types { def unapply(tpe: RefinedType): Option[(List[Type], Scope)] /** @see [[InternalApi.refinedType]] */ - @deprecated("Use `internal.refinedType` instead", "2.11.0") + @deprecated("use `internal.refinedType` instead", "2.11.0") def apply(parents: List[Type], decls: Scope)(implicit token: CompatToken): RefinedType = internal.refinedType(parents, decls) /** @see [[InternalApi.refinedType]] */ - @deprecated("Use `internal.refinedType` instead", "2.11.0") + @deprecated("use `internal.refinedType` instead", "2.11.0") def apply(parents: List[Type], decls: Scope, clazz: Symbol)(implicit token: CompatToken): RefinedType = internal.refinedType(parents, decls, clazz) } @@ -704,7 +704,7 @@ trait Types { def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] /** @see [[InternalApi.classInfoType]] */ - @deprecated("Use `internal.classInfoType` instead", "2.11.0") + @deprecated("use `internal.classInfoType` instead", "2.11.0") def apply(parents: List[Type], decls: Scope, typeSymbol: Symbol)(implicit token: CompatToken): ClassInfoType = internal.classInfoType(parents, decls, typeSymbol) } @@ -753,7 +753,7 @@ trait Types { def unapply(tpe: MethodType): Option[(List[Symbol], Type)] /** @see [[InternalApi.methodType]] */ - @deprecated("Use `internal.methodType` instead", "2.11.0") + @deprecated("use `internal.methodType` instead", "2.11.0") def apply(params: List[Symbol], resultType: Type)(implicit token: CompatToken): MethodType = internal.methodType(params, resultType) } @@ -789,7 +789,7 @@ trait Types { def unapply(tpe: NullaryMethodType): Option[(Type)] /** @see [[InternalApi.nullaryMethodType]] */ - @deprecated("Use `internal.nullaryMethodType` instead", "2.11.0") + @deprecated("use `internal.nullaryMethodType` instead", "2.11.0") def apply(resultType: Type)(implicit token: CompatToken): NullaryMethodType = internal.nullaryMethodType(resultType) } @@ -823,7 +823,7 @@ trait Types { def unapply(tpe: PolyType): Option[(List[Symbol], Type)] /** @see [[InternalApi.polyType]] */ - @deprecated("Use `internal.polyType` instead", "2.11.0") + @deprecated("use `internal.polyType` instead", "2.11.0") def apply(typeParams: List[Symbol], resultType: Type)(implicit token: CompatToken): PolyType = internal.polyType(typeParams, resultType) } @@ -861,7 +861,7 @@ trait Types { def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)] /** @see [[InternalApi.existentialType]] */ - @deprecated("Use `internal.existentialType` instead", "2.11.0") + @deprecated("use `internal.existentialType` instead", "2.11.0") def apply(quantified: List[Symbol], underlying: Type)(implicit token: CompatToken): ExistentialType = internal.existentialType(quantified, underlying) } @@ -899,7 +899,7 @@ trait Types { def unapply(tpe: AnnotatedType): Option[(List[Annotation], Type)] /** @see [[InternalApi.annotatedType]] */ - @deprecated("Use `internal.annotatedType` instead", "2.11.0") + @deprecated("use `internal.annotatedType` instead", "2.11.0") def apply(annotations: List[Annotation], underlying: Type)(implicit token: CompatToken): AnnotatedType = internal.annotatedType(annotations, underlying) } @@ -943,7 +943,7 @@ trait Types { def unapply(tpe: TypeBounds): Option[(Type, Type)] /** @see [[InternalApi.typeBounds]] */ - @deprecated("Use `internal.typeBounds` instead", "2.11.0") + @deprecated("use `internal.typeBounds` instead", "2.11.0") def apply(lo: Type, hi: Type)(implicit token: CompatToken): TypeBounds = internal.typeBounds(lo, hi) } @@ -996,7 +996,7 @@ trait Types { def unapply(tpe: BoundedWildcardType): Option[TypeBounds] /** @see [[InternalApi.boundedWildcardType]] */ - @deprecated("Use `internal.boundedWildcardType` instead", "2.11.0") + @deprecated("use `internal.boundedWildcardType` instead", "2.11.0") def apply(bounds: TypeBounds)(implicit token: CompatToken): BoundedWildcardType = internal.boundedWildcardType(bounds) } diff --git a/src/reflect/scala/reflect/internal/AnnotationCheckers.scala b/src/reflect/scala/reflect/internal/AnnotationCheckers.scala index 1ba014d19db0..9a6caff16064 100644 --- a/src/reflect/scala/reflect/internal/AnnotationCheckers.scala +++ b/src/reflect/scala/reflect/internal/AnnotationCheckers.scala @@ -45,14 +45,14 @@ trait AnnotationCheckers { * Modify the type that has thus far been inferred for a tree. All this should * do is add annotations. */ - @deprecated("Create an AnalyzerPlugin and use pluginsTyped", "2.10.1") + @deprecated("create an AnalyzerPlugin and use pluginsTyped", "2.10.1") def addAnnotations(tree: Tree, tpe: Type): Type = tpe /** * Decide whether this analyzer plugin can adapt a tree that has an annotated type to the * given type tp, taking into account the given mode (see method adapt in trait Typers). */ - @deprecated("Create an AnalyzerPlugin and use canAdaptAnnotations", "2.10.1") + @deprecated("create an AnalyzerPlugin and use canAdaptAnnotations", "2.10.1") def canAdaptAnnotations(tree: Tree, mode: Mode, pt: Type): Boolean = false /** @@ -62,7 +62,7 @@ trait AnnotationCheckers { * An implementation cannot rely on canAdaptAnnotations being called before. If the implementing * class cannot do the adapting, it should return the tree unchanged. */ - @deprecated("Create an AnalyzerPlugin and use adaptAnnotations", "2.10.1") + @deprecated("create an AnalyzerPlugin and use adaptAnnotations", "2.10.1") def adaptAnnotations(tree: Tree, mode: Mode, pt: Type): Tree = tree /** diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index db8ac9b0cbe7..ca6c893d130d 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -714,12 +714,12 @@ trait Definitions extends api.StandardDefinitions { def productProj(z:Symbol, j: Int): TermSymbol = getMemberValue(z, nme.productAccessorName(j)) /** if tpe <: ProductN[T1,...,TN], returns List(T1,...,TN) else Nil */ - @deprecated("No longer used", "2.11.0") def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNSymbol match { + @deprecated("no longer used", "2.11.0") def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNSymbol match { case Some(x) => tpe.baseType(x).typeArgs case _ => Nil } - @deprecated("No longer used", "2.11.0") def unapplyUnwrap(tpe:Type) = tpe.finalResultType.dealiasWiden match { + @deprecated("no longer used", "2.11.0") def unapplyUnwrap(tpe:Type) = tpe.finalResultType.dealiasWiden match { case RefinedType(p :: _, _) => p.dealiasWiden case tp => tp } diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index f058acb7c018..230d30c74ec3 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -477,7 +477,7 @@ class Flags extends ModifierFlags { else "private[" + privateWithin + "]" ) - @deprecated("Use flagString on the flag-carrying member", "2.10.0") + @deprecated("use flagString on the flag-carrying member", "2.10.0") private[scala] def flagsToString(flags: Long, privateWithin: String): String = { val access = accessString(flags, privateWithin) val nonAccess = flagsToString(flags & ~AccessFlags) @@ -485,7 +485,7 @@ class Flags extends ModifierFlags { List(nonAccess, access) filterNot (_ == "") mkString " " } - @deprecated("Use flagString on the flag-carrying member", "2.10.0") + @deprecated("use flagString on the flag-carrying member", "2.10.0") private[scala] def flagsToString(flags: Long): String = { // Fast path for common case if (flags == 0L) "" else { diff --git a/src/reflect/scala/reflect/internal/HasFlags.scala b/src/reflect/scala/reflect/internal/HasFlags.scala index 673ea4fdefc4..e793586e1814 100644 --- a/src/reflect/scala/reflect/internal/HasFlags.scala +++ b/src/reflect/scala/reflect/internal/HasFlags.scala @@ -84,7 +84,7 @@ trait HasFlags { def hasDefault = hasFlag(DEFAULTPARAM) && hasFlag(METHOD | PARAM) // Second condition disambiguates with TRAIT def hasJavaEnumFlag = hasFlag(JAVA_ENUM) def hasJavaAnnotationFlag = hasFlag(JAVA_ANNOTATION) - @deprecated("Use isLocalToThis instead", "2.11.0") + @deprecated("use isLocalToThis instead", "2.11.0") def hasLocalFlag = hasFlag(LOCAL) def isLocalToThis = hasFlag(LOCAL) def hasModuleFlag = hasFlag(MODULE) @@ -109,7 +109,7 @@ trait HasFlags { def isOverride = hasFlag(OVERRIDE) def isParamAccessor = hasFlag(PARAMACCESSOR) def isPrivate = hasFlag(PRIVATE) - @deprecated ("Use `hasPackageFlag` instead", "2.11.0") + @deprecated ("use `hasPackageFlag` instead", "2.11.0") def isPackage = hasFlag(PACKAGE) def isPrivateLocal = hasAllFlags(PrivateLocal) def isProtected = hasFlag(PROTECTED) diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala index 0f0f16574ee6..756300d4036f 100644 --- a/src/reflect/scala/reflect/internal/Mirrors.scala +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -175,7 +175,7 @@ trait Mirrors extends api.Mirrors { def getPackageIfDefined(fullname: TermName): Symbol = wrapMissing(getPackage(fullname)) - @deprecated("Use getPackage", "2.11.0") def getRequiredPackage(fullname: String): ModuleSymbol = + @deprecated("use getPackage", "2.11.0") def getRequiredPackage(fullname: String): ModuleSymbol = getPackage(newTermNameCached(fullname)) def getPackageObject(fullname: String): ModuleSymbol = getPackageObject(newTermName(fullname)) diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index 103f885ad4a9..a7bb127506e5 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -380,7 +380,7 @@ trait Scopes extends api.Scopes { self: SymbolTable => if (toList forall p) this else newScopeWith(toList filter p: _*) ) - @deprecated("Use `toList.reverse` instead", "2.10.0") // Used in SBT 0.12.4 + @deprecated("use `toList.reverse` instead", "2.10.0") // Used in SBT 0.12.4 def reverse: List[Symbol] = toList.reverse override def mkString(start: String, sep: String, end: String) = diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 0ac72e7d8b4e..c93ecac3fad8 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -430,14 +430,14 @@ trait StdNames { name drop idx + 2 } - @deprecated("Use unexpandedName", "2.11.0") def originalName(name: Name): Name = unexpandedName(name) - @deprecated("Use Name#dropModule", "2.11.0") def stripModuleSuffix(name: Name): Name = name.dropModule - @deprecated("Use Name#dropLocal", "2.11.0") def localToGetter(name: TermName): TermName = name.dropLocal - @deprecated("Use Name#dropLocal", "2.11.0") def dropLocalSuffix(name: Name): TermName = name.dropLocal - @deprecated("Use Name#localName", "2.11.0") def getterToLocal(name: TermName): TermName = name.localName - @deprecated("Use Name#setterName", "2.11.0") def getterToSetter(name: TermName): TermName = name.setterName - @deprecated("Use Name#getterName", "2.11.0") def getterName(name: TermName): TermName = name.getterName - @deprecated("Use Name#getterName", "2.11.0") def setterToGetter(name: TermName): TermName = name.getterName + @deprecated("use unexpandedName", "2.11.0") def originalName(name: Name): Name = unexpandedName(name) + @deprecated("use Name#dropModule", "2.11.0") def stripModuleSuffix(name: Name): Name = name.dropModule + @deprecated("use Name#dropLocal", "2.11.0") def localToGetter(name: TermName): TermName = name.dropLocal + @deprecated("use Name#dropLocal", "2.11.0") def dropLocalSuffix(name: Name): TermName = name.dropLocal + @deprecated("use Name#localName", "2.11.0") def getterToLocal(name: TermName): TermName = name.localName + @deprecated("use Name#setterName", "2.11.0") def getterToSetter(name: TermName): TermName = name.setterName + @deprecated("use Name#getterName", "2.11.0") def getterName(name: TermName): TermName = name.getterName + @deprecated("use Name#getterName", "2.11.0") def setterToGetter(name: TermName): TermName = name.getterName /** * Convert `Tuple2$mcII` to `Tuple2`, or `T1$sp` to `T1`. diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 6d988479af1d..f60b4f6a8df4 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -63,7 +63,7 @@ abstract class SymbolTable extends macros.Universe def isPastTyper = false protected def isDeveloper: Boolean = settings.debug - @deprecated("Use devWarning if this is really a warning; otherwise use log", "2.11.0") + @deprecated("use devWarning if this is really a warning; otherwise use log", "2.11.0") def debugwarn(msg: => String): Unit = devWarning(msg) /** Override with final implementation for inlining. */ @@ -416,7 +416,7 @@ abstract class SymbolTable extends macros.Universe */ def isCompilerUniverse = false - @deprecated("Use enteringPhase", "2.10.0") // Used in SBT 0.12.4 + @deprecated("use enteringPhase", "2.10.0") // Used in SBT 0.12.4 @inline final def atPhase[T](ph: Phase)(op: => T): T = enteringPhase(ph)(op) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 8f24b435b3c1..49202cd71e2d 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -584,7 +584,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isAnonymousClass = false def isCaseClass = false def isConcreteClass = false - @deprecated("Trait implementation classes have been removed in Scala 2.12", "2.12.0") + @deprecated("trait implementation classes have been removed in Scala 2.12", "2.12.0") def isImplClass = false def isJavaInterface = false def isNumericValueClass = false @@ -1002,7 +1002,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isTopLevel = owner.isPackageClass /** Is this symbol defined in a block? */ - @deprecated("Use isLocalToBlock instead", "2.11.0") + @deprecated("use isLocalToBlock instead", "2.11.0") final def isLocal: Boolean = owner.isTerm /** Is this symbol defined in a block? */ @@ -1218,7 +1218,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ------ name attribute -------------------------------------------------------------- - @deprecated("Use unexpandedName", "2.11.0") def originalName: Name = unexpandedName + @deprecated("use unexpandedName", "2.11.0") def originalName: Name = unexpandedName /** If this symbol has an expanded name, its original (unexpanded) name, * otherwise the name itself. @@ -2374,7 +2374,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => Nil ) - @deprecated("Use `superSymbolIn` instead", "2.11.0") + @deprecated("use `superSymbolIn` instead", "2.11.0") final def superSymbol(base: Symbol): Symbol = superSymbolIn(base) /** The symbol accessed by a super in the definition of this symbol when @@ -2391,7 +2391,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => sym } - @deprecated("Use `getterIn` instead", "2.11.0") + @deprecated("use `getterIn` instead", "2.11.0") final def getter(base: Symbol): Symbol = getterIn(base) /** The getter of this value or setter definition in class `base`, or NoSymbol if none exists. */ @@ -2402,7 +2402,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def setterName: TermName = name.setterName def localName: TermName = name.localName - @deprecated("Use `setterIn` instead", "2.11.0") + @deprecated("use `setterIn` instead", "2.11.0") final def setter(base: Symbol, hasExpandedName: Boolean = needsExpandedSetterName): Symbol = setterIn(base, hasExpandedName) diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index cba34aa22065..c9dfd0c337a8 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -44,7 +44,7 @@ trait Trees extends api.Trees { private[this] var rawtpe: Type = _ final def tpe = rawtpe - @deprecated("Use setType", "2.11.0") def tpe_=(t: Type): Unit = setType(t) + @deprecated("use setType", "2.11.0") def tpe_=(t: Type): Unit = setType(t) def clearType(): this.type = this setType null def setType(tp: Type): this.type = { rawtpe = tp; this } @@ -54,7 +54,7 @@ trait Trees extends api.Trees { def symbol_=(sym: Symbol) { throw new UnsupportedOperationException("symbol_= inapplicable for " + this) } def setSymbol(sym: Symbol): this.type = { symbol = sym; this } def hasSymbolField = false - @deprecated("Use hasSymbolField", "2.11.0") def hasSymbol = hasSymbolField + @deprecated("use hasSymbolField", "2.11.0") def hasSymbol = hasSymbolField def isDef = false @@ -1095,7 +1095,7 @@ trait Trees extends api.Trees { object noSelfType extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) with CannotHaveAttrs object pendingSuperCall extends Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List()) with CannotHaveAttrs - @deprecated("Use `noSelfType` instead", "2.11.0") lazy val emptyValDef = noSelfType + @deprecated("use `noSelfType` instead", "2.11.0") lazy val emptyValDef = noSelfType def newValDef(sym: Symbol, rhs: Tree)( mods: Modifiers = Modifiers(sym.flags), diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index a649f6f92658..895bb60a081f 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3847,7 +3847,7 @@ trait Types case _ => false }) - @deprecated("Use isRawType", "2.10.1") // presently used by sbt + @deprecated("use isRawType", "2.10.1") // presently used by sbt def isRaw(sym: Symbol, args: List[Type]) = ( !phase.erasedTypes && args.isEmpty diff --git a/src/reflect/scala/reflect/internal/annotations/package.scala b/src/reflect/scala/reflect/internal/annotations/package.scala index ef299a600cc4..8a42f1479d96 100644 --- a/src/reflect/scala/reflect/internal/annotations/package.scala +++ b/src/reflect/scala/reflect/internal/annotations/package.scala @@ -1,6 +1,6 @@ package scala.reflect.internal package object annotations { - @deprecated("Use scala.annotation.compileTimeOnly instead", "2.11.0") + @deprecated("use scala.annotation.compileTimeOnly instead", "2.11.0") type compileTimeOnly = scala.annotation.compileTimeOnly -} \ No newline at end of file +} diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index af5128163b27..c3f92f1bce95 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -449,7 +449,7 @@ private[internal] trait TypeMaps { (pre eq NoType) || (pre eq NoPrefix) || !isPossiblePrefix(clazz) ) - @deprecated("Use new AsSeenFromMap instead", "2.12.0") + @deprecated("use new AsSeenFromMap instead", "2.12.0") final def newAsSeenFromMap(pre: Type, clazz: Symbol): AsSeenFromMap = new AsSeenFromMap(pre, clazz) /** A map to compute the asSeenFrom method. diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala index 0192d318069a..e0f681d910b6 100644 --- a/src/reflect/scala/reflect/internal/util/Position.scala +++ b/src/reflect/scala/reflect/internal/util/Position.scala @@ -240,12 +240,12 @@ private[util] trait DeprecatedPosition { @deprecated("use `lineCaret`", since="2.11.0") def lineWithCarat(maxWidth: Int): (String, String) = ("", "") - @deprecated("Use `withSource(source)` and `withShift`", "2.11.0") + @deprecated("use `withSource(source)` and `withShift`", "2.11.0") def withSource(source: SourceFile, shift: Int): Position = this withSource source withShift shift - @deprecated("Use `start` instead", "2.11.0") + @deprecated("use `start` instead", "2.11.0") def startOrPoint: Int = if (isRange) start else point - @deprecated("Use `end` instead", "2.11.0") + @deprecated("use `end` instead", "2.11.0") def endOrPoint: Int = if (isRange) end else point } diff --git a/src/reflect/scala/reflect/macros/ExprUtils.scala b/src/reflect/scala/reflect/macros/ExprUtils.scala index c438653c9286..3e2655b722c9 100644 --- a/src/reflect/scala/reflect/macros/ExprUtils.scala +++ b/src/reflect/scala/reflect/macros/ExprUtils.scala @@ -12,54 +12,54 @@ trait ExprUtils { self: blackbox.Context => /** Shorthand for `Literal(Constant(null))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literalNull: Expr[Null] /** Shorthand for `Literal(Constant(()))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literalUnit: Expr[Unit] /** Shorthand for `Literal(Constant(true))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literalTrue: Expr[Boolean] /** Shorthand for `Literal(Constant(false))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literalFalse: Expr[Boolean] /** Shorthand for `Literal(Constant(x: Boolean))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: Boolean): Expr[Boolean] /** Shorthand for `Literal(Constant(x: Byte))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: Byte): Expr[Byte] /** Shorthand for `Literal(Constant(x: Short))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: Short): Expr[Short] /** Shorthand for `Literal(Constant(x: Int))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: Int): Expr[Int] /** Shorthand for `Literal(Constant(x: Long))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: Long): Expr[Long] /** Shorthand for `Literal(Constant(x: Float))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: Float): Expr[Float] /** Shorthand for `Literal(Constant(x: Double))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: Double): Expr[Double] /** Shorthand for `Literal(Constant(x: String))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: String): Expr[String] /** Shorthand for `Literal(Constant(x: Char))` in the underlying `universe`. */ - @deprecated("Use quasiquotes instead", "2.11.0") + @deprecated("use quasiquotes instead", "2.11.0") def literal(x: Char): Expr[Char] } diff --git a/src/reflect/scala/reflect/macros/Names.scala b/src/reflect/scala/reflect/macros/Names.scala index 4f3448e1ed02..028dda1de24f 100644 --- a/src/reflect/scala/reflect/macros/Names.scala +++ b/src/reflect/scala/reflect/macros/Names.scala @@ -34,15 +34,15 @@ trait Names { self: blackbox.Context => /** $freshNameNoParams */ - @deprecated("Use freshName instead", "2.11.0") + @deprecated("use freshName instead", "2.11.0") def fresh(): String /** $freshNameStringParam */ - @deprecated("Use freshName instead", "2.11.0") + @deprecated("use freshName instead", "2.11.0") def fresh(name: String): String /** $freshNameNameParam */ - @deprecated("Use freshName instead", "2.11.0") + @deprecated("use freshName instead", "2.11.0") def fresh[NameType <: Name](name: NameType): NameType /** $freshNameNoParams */ diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index bd608601dc08..06d2e999b2a0 100644 --- a/src/reflect/scala/reflect/macros/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -53,7 +53,7 @@ trait Typers { /** @see `Typers.typecheck` */ - @deprecated("Use `c.typecheck` instead", "2.11.0") + @deprecated("use `c.typecheck` instead", "2.11.0") def typeCheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = typecheck(tree, TERMmode, pt, silent, withImplicitViewsDisabled, withMacrosDisabled) @@ -101,7 +101,7 @@ trait Typers { /** Recursively resets locally defined symbols and types in a given tree. * WARNING: Don't use this API, go for [[untypecheck]] instead. */ - @deprecated("Use `c.untypecheck` instead", "2.11.0") + @deprecated("use `c.untypecheck` instead", "2.11.0") def resetLocalAttrs(tree: Tree): Tree /** In the current implementation of Scala's reflection API, untyped trees (also known as parser trees or unattributed trees) diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala index 3b571695654e..51a7566bb811 100644 --- a/src/reflect/scala/reflect/macros/Universe.scala +++ b/src/reflect/scala/reflect/macros/Universe.scala @@ -332,7 +332,7 @@ abstract class Universe extends scala.reflect.api.Universe { } /** @see [[internal.gen]] */ - @deprecated("Use `internal.gen` instead", "2.11.0") + @deprecated("use `internal.gen` instead", "2.11.0") val treeBuild: TreeGen /** @inheritdoc */ @@ -345,94 +345,94 @@ abstract class Universe extends scala.reflect.api.Universe { /** Scala 2.10 compatibility enrichments for Symbol. */ implicit class MacroCompatibleSymbol(symbol: Symbol) { /** @see [[InternalMacroApi.attachments]] */ - @deprecated("Use `internal.attachments` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.attachments` instead or import `internal.decorators._` for infix syntax", "2.11.0") def attachments: Attachments { type Pos = Position } = internal.attachments(symbol) /** @see [[InternalMacroApi.updateAttachment]] */ - @deprecated("Use `internal.updateAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.updateAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") def updateAttachment[T: ClassTag](attachment: T): Symbol = internal.updateAttachment[T](symbol, attachment) /** @see [[InternalMacroApi.removeAttachment]] */ - @deprecated("Use `internal.removeAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.removeAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") def removeAttachment[T: ClassTag]: Symbol = internal.removeAttachment[T](symbol) /** @see [[InternalMacroApi.setInfo]] */ - @deprecated("Use `internal.setInfo` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setInfo` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setTypeSignature(tpe: Type): Symbol = internal.setInfo(symbol, tpe) /** @see [[InternalMacroApi.setAnnotations]] */ - @deprecated("Use `internal.setAnnotations` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setAnnotations` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setAnnotations(annots: Annotation*): Symbol = internal.setAnnotations(symbol, annots: _*) /** @see [[InternalMacroApi.setName]] */ - @deprecated("Use `internal.setName` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setName` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setName(name: Name): Symbol = internal.setName(symbol, name) /** @see [[InternalMacroApi.setPrivateWithin]] */ - @deprecated("Use `internal.setPrivateWithin` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setPrivateWithin` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setPrivateWithin(sym: Symbol): Symbol = internal.setPrivateWithin(symbol, sym) } /** Scala 2.10 compatibility enrichments for TypeTree. */ implicit class MacroCompatibleTree(tree: Tree) { /** @see [[InternalMacroApi.attachments]] */ - @deprecated("Use `internal.attachments` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.attachments` instead or import `internal.decorators._` for infix syntax", "2.11.0") def attachments: Attachments { type Pos = Position } = internal.attachments(tree) /** @see [[InternalMacroApi.updateAttachment]] */ - @deprecated("Use `internal.updateAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.updateAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") def updateAttachment[T: ClassTag](attachment: T): Tree = internal.updateAttachment[T](tree, attachment) /** @see [[InternalMacroApi.removeAttachment]] */ - @deprecated("Use `internal.removeAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.removeAttachment` instead or import `internal.decorators._` for infix syntax", "2.11.0") def removeAttachment[T: ClassTag]: Tree = internal.removeAttachment[T](tree) /** @see [[InternalMacroApi.setPos]] */ - @deprecated("Use `internal.setPos` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setPos` instead or import `internal.decorators._` for infix syntax", "2.11.0") def pos_=(pos: Position): Unit = internal.setPos(tree, pos) /** @see [[InternalMacroApi.setPos]] */ - @deprecated("Use `internal.setPos` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setPos` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setPos(newpos: Position): Tree = internal.setPos(tree, newpos) /** @see [[InternalMacroApi.setType]] */ - @deprecated("Use `internal.setType` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setType` instead or import `internal.decorators._` for infix syntax", "2.11.0") def tpe_=(t: Type): Unit = internal.setType(tree, t) /** @see [[InternalMacroApi.setType]] */ - @deprecated("Use `internal.setType` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setType` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setType(tp: Type): Tree = internal.setType(tree, tp) /** @see [[InternalMacroApi.defineType]] */ - @deprecated("Use `internal.defineType` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.defineType` instead or import `internal.decorators._` for infix syntax", "2.11.0") def defineType(tp: Type): Tree = internal.defineType(tree, tp) /** @see [[InternalMacroApi.setSymbol]] */ - @deprecated("Use `internal.setSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def symbol_=(sym: Symbol): Unit = internal.setSymbol(tree, sym) /** @see [[InternalMacroApi.setSymbol]] */ - @deprecated("Use `internal.setSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setSymbol` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setSymbol(sym: Symbol): Tree = internal.setSymbol(tree, sym) } /** Scala 2.10 compatibility enrichments for TypeTree. */ implicit class CompatibleTypeTree(tt: TypeTree) { /** @see [[InternalMacroApi.setOriginal]] */ - @deprecated("Use `internal.setOriginal` instead or import `internal.decorators._` for infix syntax", "2.11.0") + @deprecated("use `internal.setOriginal` instead or import `internal.decorators._` for infix syntax", "2.11.0") def setOriginal(tree: Tree): TypeTree = internal.setOriginal(tt, tree) } /** @see [[InternalMacroApi.captureVariable]] */ - @deprecated("Use `internal.captureVariable` instead", "2.11.0") + @deprecated("use `internal.captureVariable` instead", "2.11.0") def captureVariable(vble: Symbol): Unit = internal.captureVariable(vble) /** @see [[InternalMacroApi.captureVariable]] */ - @deprecated("Use `internal.referenceCapturedVariable` instead", "2.11.0") + @deprecated("use `internal.referenceCapturedVariable` instead", "2.11.0") def referenceCapturedVariable(vble: Symbol): Tree = internal.referenceCapturedVariable(vble) /** @see [[InternalMacroApi.captureVariable]] */ - @deprecated("Use `internal.capturedVariableType` instead", "2.11.0") + @deprecated("use `internal.capturedVariableType` instead", "2.11.0") def capturedVariableType(vble: Symbol): Type = internal.capturedVariableType(vble) } diff --git a/src/reflect/scala/reflect/macros/package.scala b/src/reflect/scala/reflect/macros/package.scala index b63d419d617b..3bb1bdf7e31c 100644 --- a/src/reflect/scala/reflect/macros/package.scala +++ b/src/reflect/scala/reflect/macros/package.scala @@ -23,6 +23,6 @@ package object macros { * and `scala.reflect.macros.whitebox.Context`. The original `Context` is left in place for compatibility reasons, * but it is now deprecated, nudging the users to choose between blackbox and whitebox macros. */ - @deprecated("Use blackbox.Context or whitebox.Context instead", "2.11.0") + @deprecated("use blackbox.Context or whitebox.Context instead", "2.11.0") type Context = whitebox.Context -} \ No newline at end of file +} diff --git a/test/files/neg/classmanifests_new_deprecations.check b/test/files/neg/classmanifests_new_deprecations.check index 1b63303fd4c8..ed6f42d00ceb 100644 --- a/test/files/neg/classmanifests_new_deprecations.check +++ b/test/files/neg/classmanifests_new_deprecations.check @@ -1,25 +1,25 @@ -classmanifests_new_deprecations.scala:2: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): Use `scala.reflect.ClassTag` instead +classmanifests_new_deprecations.scala:2: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): use `scala.reflect.ClassTag` instead def cm1[T: ClassManifest] = ??? ^ -classmanifests_new_deprecations.scala:3: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): Use `scala.reflect.ClassTag` instead +classmanifests_new_deprecations.scala:3: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): use `scala.reflect.ClassTag` instead def cm2[T](implicit evidence$1: ClassManifest[T]) = ??? ^ -classmanifests_new_deprecations.scala:4: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): Use `scala.reflect.ClassTag` instead +classmanifests_new_deprecations.scala:4: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): use `scala.reflect.ClassTag` instead val cm3: ClassManifest[Int] = null ^ -classmanifests_new_deprecations.scala:6: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:6: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): use scala.reflect.ClassTag instead def rcm1[T: scala.reflect.ClassManifest] = ??? ^ -classmanifests_new_deprecations.scala:7: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:7: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): use scala.reflect.ClassTag instead def rcm2[T](implicit evidence$1: scala.reflect.ClassManifest[T]) = ??? ^ -classmanifests_new_deprecations.scala:8: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:8: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): use scala.reflect.ClassTag instead val rcm3: scala.reflect.ClassManifest[Int] = null ^ -classmanifests_new_deprecations.scala:10: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): Use `scala.reflect.ClassTag` instead +classmanifests_new_deprecations.scala:10: warning: type ClassManifest in object Predef is deprecated (since 2.10.0): use `scala.reflect.ClassTag` instead type CM[T] = ClassManifest[T] ^ -classmanifests_new_deprecations.scala:15: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:15: warning: type ClassManifest in package reflect is deprecated (since 2.10.0): use scala.reflect.ClassTag instead type RCM[T] = scala.reflect.ClassManifest[T] ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/delayed-init-ref.check b/test/files/neg/delayed-init-ref.check index 1b6ba5c3641f..2913b1858f72 100644 --- a/test/files/neg/delayed-init-ref.check +++ b/test/files/neg/delayed-init-ref.check @@ -4,8 +4,7 @@ delayed-init-ref.scala:17: warning: Selecting value vall from object O, which ex delayed-init-ref.scala:19: warning: Selecting value vall from object O, which extends scala.DelayedInit, is likely to yield an uninitialized value println(vall) // warn ^ -delayed-init-ref.scala:28: warning: trait DelayedInit in package scala is deprecated (since 2.11.0): DelayedInit semantics can be surprising. Support for `App` will continue. -See the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0-RC1 +delayed-init-ref.scala:28: warning: trait DelayedInit in package scala is deprecated (since 2.11.0): DelayedInit semantics can be surprising. Support for `App` will continue. See the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0-RC1 trait Before extends DelayedInit { ^ delayed-init-ref.scala:40: warning: Selecting value foo from trait UserContext, which extends scala.DelayedInit, is likely to yield an uninitialized value diff --git a/test/files/neg/names-defaults-neg-warn.check b/test/files/neg/names-defaults-neg-warn.check index 14a1e50e6892..3ff7d67cc367 100644 --- a/test/files/neg/names-defaults-neg-warn.check +++ b/test/files/neg/names-defaults-neg-warn.check @@ -1,7 +1,7 @@ -names-defaults-neg-warn.scala:11: warning: the parameter name s is deprecated: Use x instead +names-defaults-neg-warn.scala:11: warning: the parameter name s is deprecated: use x instead deprNam2.f(s = "dlfkj") ^ -names-defaults-neg-warn.scala:12: warning: the parameter name x is deprecated: Use s instead +names-defaults-neg-warn.scala:12: warning: the parameter name x is deprecated: use s instead deprNam2.g(x = "dlkjf") ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check index e6929cb52ea6..0a7b1a7157e2 100644 --- a/test/files/neg/names-defaults-neg.check +++ b/test/files/neg/names-defaults-neg.check @@ -112,7 +112,7 @@ names-defaults-neg.scala:90: error: deprecated parameter name x has to be distin names-defaults-neg.scala:91: error: deprecated parameter name a has to be distinct from any other parameter name (deprecated or not). def deprNam2(a: String)(@deprecatedName('a) b: Int) = 1 ^ -names-defaults-neg.scala:93: warning: the parameter name y is deprecated: Use b instead +names-defaults-neg.scala:93: warning: the parameter name y is deprecated: use b instead deprNam3(y = 10, b = 2) ^ names-defaults-neg.scala:93: error: parameter 'b' is already specified at parameter position 1 diff --git a/test/files/neg/t6406-regextract.check b/test/files/neg/t6406-regextract.check index b49b6656f540..41b362f455da 100644 --- a/test/files/neg/t6406-regextract.check +++ b/test/files/neg/t6406-regextract.check @@ -1,4 +1,4 @@ -t6406-regextract.scala:4: warning: method unapplySeq in class Regex is deprecated (since 2.11.0): Extracting a match result from anything but a CharSequence or Match is deprecated +t6406-regextract.scala:4: warning: method unapplySeq in class Regex is deprecated (since 2.11.0): extracting a match result from anything but a CharSequence or Match is deprecated List(1) collect { case r(i) => i } ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/run/t3235-minimal.check b/test/files/run/t3235-minimal.check index 5b0657219161..374ddc79fe92 100644 --- a/test/files/run/t3235-minimal.check +++ b/test/files/run/t3235-minimal.check @@ -1,12 +1,12 @@ -t3235-minimal.scala:3: warning: method round in class RichInt is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? +t3235-minimal.scala:3: warning: method round in class RichInt is deprecated (since 2.11.0): this is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? assert(123456789.round == 123456789) ^ -t3235-minimal.scala:4: warning: method round in package math is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? +t3235-minimal.scala:4: warning: method round in package math is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? assert(math.round(123456789) == 123456789) ^ -t3235-minimal.scala:5: warning: method round in class RichLong is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? +t3235-minimal.scala:5: warning: method round in class RichLong is deprecated (since 2.11.0): this is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? assert(1234567890123456789L.round == 1234567890123456789L) ^ -t3235-minimal.scala:6: warning: method round in package math is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? +t3235-minimal.scala:6: warning: method round in package math is deprecated (since 2.11.0): This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? assert(math.round(1234567890123456789L) == 1234567890123456789L) ^ From be38ebba3f32816a150012727d3351570718bcf6 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Sat, 2 Apr 2016 15:27:56 +0200 Subject: [PATCH 072/153] Add since arg to deprecationWarning and use it --- .../scala/tools/nsc/CompilationUnits.scala | 2 +- src/compiler/scala/tools/nsc/Global.scala | 8 ++-- src/compiler/scala/tools/nsc/Reporting.scala | 41 +++++++++++++------ .../scala/tools/nsc/ast/parser/Parsers.scala | 18 ++++---- .../scala/tools/nsc/ast/parser/Scanners.scala | 18 ++++---- .../scala/tools/nsc/javac/JavaParsers.scala | 2 +- .../scala/tools/nsc/javac/JavaScanners.scala | 4 +- .../patmat/ScalacPatternExpanders.scala | 2 +- .../tools/nsc/typechecker/Adaptations.scala | 2 +- .../tools/nsc/typechecker/Contexts.scala | 4 +- .../tools/nsc/typechecker/NamesDefaults.scala | 9 ++-- .../tools/nsc/typechecker/RefChecks.scala | 11 ++--- .../scala/tools/nsc/typechecker/Typers.scala | 15 +++---- .../tools/reflect/FormatInterpolator.scala | 2 +- .../scala/collection/immutable/Range.scala | 8 ++-- .../scala/concurrent/ExecutionContext.scala | 2 +- src/library/scala/concurrent/Future.scala | 10 ++--- src/library/scala/math/BigDecimal.scala | 16 ++++---- src/library/scala/util/Try.scala | 2 +- .../scala/reflect/internal/Reporting.scala | 2 +- .../scala/reflect/internal/Variances.scala | 2 +- .../reflect/internal/util/StringOps.scala | 4 +- .../scala/reflect/runtime/JavaUniverse.scala | 2 +- .../scala/tools/nsc/interpreter/IMain.scala | 2 +- test/files/jvm/future-spec.check | 4 +- test/files/jvm/scala-concurrent-tck.check | 2 +- test/files/jvm/serialization-new.check | 4 +- test/files/jvm/serialization.check | 4 +- test/files/neg/checksensible.check | 2 +- test/files/neg/t7783.check | 10 ++--- test/files/run/bitsets.check | 2 +- test/files/run/collection-stacks.check | 2 +- test/files/run/colltest.check | 2 +- test/files/run/delay-bad.check | 2 +- .../files/run/future-flatmap-exec-count.check | 2 +- .../run/reflection-java-annotations.check | 2 +- .../run/repl-no-imports-no-predef-power.check | 2 +- test/files/run/repl-power.check | 2 +- test/files/run/richs.check | 2 +- test/files/run/sbt-icode-interface.check | 2 +- test/files/run/t2212.check | 2 +- test/files/run/t3361.check | 2 +- test/files/run/t3647.check | 2 +- test/files/run/t3888.check | 2 +- test/files/run/t3970.check | 2 +- test/files/run/t3996.check | 2 +- test/files/run/t4080.check | 2 +- test/files/run/t4396.check | 2 +- test/files/run/t4461.check | 2 +- test/files/run/t4594-repl-settings.scala | 2 +- test/files/run/t4680.check | 2 +- test/files/run/t4813.check | 2 +- test/files/run/t5428.check | 2 +- test/files/run/t576.check | 2 +- test/files/run/t6111.check | 2 +- test/files/run/t6292.check | 2 +- test/files/run/t6329_repl.check | 8 ++-- test/files/run/t6329_repl_bug.check | 2 +- test/files/run/t6329_vanilla_bug.check | 2 +- test/files/run/t6481.check | 2 +- test/files/run/t6690.check | 2 +- test/files/run/t6863.check | 2 +- test/files/run/t6935.check | 2 +- test/files/run/t8549.check | 2 +- test/files/run/unittest_collection.check | 2 +- .../symtab/SymbolTableForUnitTesting.scala | 2 +- 66 files changed, 160 insertions(+), 132 deletions(-) diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 34b07a26513d..02d9b0d9133b 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -128,7 +128,7 @@ trait CompilationUnits { global: Global => final def warning(pos: Position, msg: String): Unit = reporter.warning(pos, msg) @deprecated("Call global.currentRun.reporting.deprecationWarning directly instead.", "2.11.2") - final def deprecationWarning(pos: Position, msg: String): Unit = currentRun.reporting.deprecationWarning(pos, msg) + final def deprecationWarning(pos: Position, msg: String, since: String): Unit = currentRun.reporting.deprecationWarning(pos, msg, since) @deprecated("Call global.currentRun.reporting.uncheckedWarning directly instead.", "2.11.2") final def uncheckedWarning(pos: Position, msg: String): Unit = currentRun.reporting.uncheckedWarning(pos, msg) diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 7417d9c09ddc..9d6693c00fd8 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1054,9 +1054,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) var currentUnit: CompilationUnit = NoCompilationUnit // used in sbt - def uncheckedWarnings: List[(Position, String)] = reporting.uncheckedWarnings + def uncheckedWarnings: List[(Position, String)] = reporting.uncheckedWarnings.map{case (pos, (msg, since)) => (pos, msg)} // used in sbt - def deprecationWarnings: List[(Position, String)] = reporting.deprecationWarnings + def deprecationWarnings: List[(Position, String)] = reporting.deprecationWarnings.map{case (pos, (msg, since)) => (pos, msg)} private class SyncedCompilationBuffer { self => private val underlying = new mutable.ArrayBuffer[CompilationUnit] @@ -1267,11 +1267,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter) private def warnDeprecatedAndConflictingSettings(unit: CompilationUnit) { // issue warnings for any usage of deprecated settings settings.userSetSettings filter (_.isDeprecated) foreach { s => - currentRun.reporting.deprecationWarning(NoPosition, s.name + " is deprecated: " + s.deprecationMessage.get) + currentRun.reporting.deprecationWarning(NoPosition, s.name + " is deprecated: " + s.deprecationMessage.get, "") } val supportedTarget = "jvm-1.8" if (settings.target.value != supportedTarget) { - currentRun.reporting.deprecationWarning(NoPosition, settings.target.name + ":" + settings.target.value + " is deprecated and has no effect, setting to " + supportedTarget) + currentRun.reporting.deprecationWarning(NoPosition, settings.target.name + ":" + settings.target.value + " is deprecated and has no effect, setting to " + supportedTarget, "2.12.0") settings.target.value = supportedTarget } settings.conflictWarning.foreach(reporter.warning(NoPosition, _)) diff --git a/src/compiler/scala/tools/nsc/Reporting.scala b/src/compiler/scala/tools/nsc/Reporting.scala index 325537a5a8d9..01c583bea31b 100644 --- a/src/compiler/scala/tools/nsc/Reporting.scala +++ b/src/compiler/scala/tools/nsc/Reporting.scala @@ -30,17 +30,33 @@ trait Reporting extends scala.reflect.internal.Reporting { self: ast.Positions w def this(what: String, booleanSetting: Settings#BooleanSetting) { this(what, () => booleanSetting, booleanSetting) } - val warnings = mutable.LinkedHashMap[Position, String]() - def warn(pos: Position, msg: String) = + val warnings = mutable.LinkedHashMap[Position, (String, String)]() + def warn(pos: Position, msg: String, since: String = "") = if (doReport()) reporter.warning(pos, msg) - else if (!(warnings contains pos)) warnings += ((pos, msg)) + else if (!(warnings contains pos)) warnings += ((pos, (msg, since))) def summarize() = if (warnings.nonEmpty && (setting.isDefault || doReport())) { - val numWarnings = warnings.size - val warningVerb = if (numWarnings == 1) "was" else "were" - val warningCount = countElementsAsString(numWarnings, s"$what warning") - - reporter.warning(NoPosition, s"there $warningVerb $warningCount; re-run with ${setting.name} for details") + val sinceAndAmount = mutable.TreeMap[String, Int]() + warnings.valuesIterator.foreach { case (_, since) => + val value = sinceAndAmount.get(since) + if (value.isDefined) sinceAndAmount += ((since, value.get + 1)) + else sinceAndAmount += ((since, 1)) + } + val deprecationSummary = sinceAndAmount.size > 1 + sinceAndAmount.foreach { case (since, amount) => + val numWarnings = amount + val warningsSince = if (since.nonEmpty) s" (since $since)" else "" + val warningVerb = if (numWarnings == 1) "was" else "were" + val warningCount = countElementsAsString(numWarnings, s"$what warning") + val rerun = if (deprecationSummary) "" else s"; re-run with ${setting.name} for details" + reporter.warning(NoPosition, s"there $warningVerb $warningCount$warningsSince$rerun") + } + if (deprecationSummary) { + val numWarnings = warnings.size + val warningVerb = if (numWarnings == 1) "was" else "were" + val warningCount = countElementsAsString(numWarnings, s"$what warning") + reporter.warning(NoPosition, s"there $warningVerb $warningCount in total; re-run with ${setting.name} for details") + } } } @@ -53,7 +69,7 @@ trait Reporting extends scala.reflect.internal.Reporting { self: ast.Positions w private val _allConditionalWarnings = List(_deprecationWarnings, _uncheckedWarnings, _featureWarnings, _inlinerWarnings) // TODO: remove in favor of the overload that takes a Symbol, give that argument a default (NoSymbol) - def deprecationWarning(pos: Position, msg: String): Unit = _deprecationWarnings.warn(pos, msg) + def deprecationWarning(pos: Position, msg: String, since: String): Unit = _deprecationWarnings.warn(pos, msg, since) def uncheckedWarning(pos: Position, msg: String): Unit = _uncheckedWarnings.warn(pos, msg) def featureWarning(pos: Position, msg: String): Unit = _featureWarnings.warn(pos, msg) def inlinerWarning(pos: Position, msg: String): Unit = _inlinerWarnings.warn(pos, msg) @@ -66,11 +82,12 @@ trait Reporting extends scala.reflect.internal.Reporting { self: ast.Positions w def allConditionalWarnings = _allConditionalWarnings flatMap (_.warnings) // behold! the symbol that caused the deprecation warning (may not be deprecated itself) - def deprecationWarning(pos: Position, sym: Symbol, msg: String): Unit = _deprecationWarnings.warn(pos, msg) + def deprecationWarning(pos: Position, sym: Symbol, msg: String, since: String): Unit = _deprecationWarnings.warn(pos, msg, since) def deprecationWarning(pos: Position, sym: Symbol): Unit = { - val version = sym.deprecationVersion match { case Some(ver) => s" (since $ver)" case _ => "" } + val version = sym.deprecationVersion.getOrElse("") + val since = if (version.isEmpty) version else s" (since $version)" val message = sym.deprecationMessage match { case Some(msg) => s": $msg" case _ => "" } - deprecationWarning(pos, sym, s"$sym${sym.locationString} is deprecated$version$message") + deprecationWarning(pos, sym, s"$sym${sym.locationString} is deprecated$since$message", version) } private[this] var reportedFeature = Set[Symbol]() diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 8413183ab632..f59deafe1b4c 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -39,7 +39,7 @@ trait ParsersCommon extends ScannersCommon { self => */ abstract class ParserCommon { val in: ScannerCommon - def deprecationWarning(off: Offset, msg: String): Unit + def deprecationWarning(off: Offset, msg: String, since: String): Unit def accept(token: Token): Int /** Methods inParensOrError and similar take a second argument which, should @@ -154,7 +154,7 @@ self => // suppress warnings; silent abort on errors def warning(offset: Offset, msg: String): Unit = () - def deprecationWarning(offset: Offset, msg: String): Unit = () + def deprecationWarning(offset: Offset, msg: String, since: String): Unit = () def syntaxError(offset: Offset, msg: String): Unit = throw new MalformedInput(offset, msg) def incompleteInputError(msg: String): Unit = throw new MalformedInput(source.content.length - 1, msg) @@ -206,8 +206,8 @@ self => override def warning(offset: Offset, msg: String): Unit = reporter.warning(o2p(offset), msg) - override def deprecationWarning(offset: Offset, msg: String): Unit = - currentRun.reporting.deprecationWarning(o2p(offset), msg) + override def deprecationWarning(offset: Offset, msg: String, since: String): Unit = + currentRun.reporting.deprecationWarning(o2p(offset), msg, since) private var smartParsing = false @inline private def withSmartParsing[T](body: => T): T = { @@ -1822,7 +1822,7 @@ self => val hasEq = in.token == EQUALS if (hasVal) { - if (hasEq) deprecationWarning(in.offset, "val keyword in for comprehension is deprecated") + if (hasEq) deprecationWarning(in.offset, "val keyword in for comprehension is deprecated", "2.10.0") else syntaxError(in.offset, "val in for comprehension must be followed by assignment") } @@ -2358,7 +2358,7 @@ self => while (in.token == VIEWBOUND) { val msg = "Use an implicit parameter instead.\nExample: Instead of `def f[A <% Int](a: A)` use `def f[A](a: A)(implicit ev: A => Int)`." if (settings.future) - deprecationWarning(in.offset, s"View bounds are deprecated. $msg") + deprecationWarning(in.offset, s"View bounds are deprecated. $msg", "2.12.0") contextBoundBuf += atPos(in.skipToken())(makeFunctionTypeTree(List(Ident(pname)), typ())) } while (in.token == COLON) { @@ -2652,14 +2652,14 @@ self => if (isStatSep || in.token == RBRACE) { if (restype.isEmpty) { if (settings.future) - deprecationWarning(in.lastOffset, s"Procedure syntax is deprecated. Convert procedure `$name` to method by adding `: Unit`.") + deprecationWarning(in.lastOffset, s"Procedure syntax is deprecated. Convert procedure `$name` to method by adding `: Unit`.", "2.12.0") restype = scalaUnitConstr } newmods |= Flags.DEFERRED EmptyTree } else if (restype.isEmpty && in.token == LBRACE) { if (settings.future) - deprecationWarning(in.offset, s"Procedure syntax is deprecated. Convert procedure `$name` to method by adding `: Unit =`.") + deprecationWarning(in.offset, s"Procedure syntax is deprecated. Convert procedure `$name` to method by adding `: Unit =`.", "2.12.0") restype = scalaUnitConstr blockExpr() } else { @@ -2921,7 +2921,7 @@ self => case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred => copyValDef(vdef)(mods = mods | Flags.PRESUPER) case tdef @ TypeDef(mods, name, tparams, rhs) => - deprecationWarning(tdef.pos.point, "early type members are deprecated. Move them to the regular body: the semantics are the same.") + deprecationWarning(tdef.pos.point, "early type members are deprecated. Move them to the regular body: the semantics are the same.", "2.11.0") treeCopy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs) case docdef @ DocDef(comm, rhs) => treeCopy.DocDef(docdef, comm, rhs) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 3d8f5a2dd3f5..891858ba7b95 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -35,7 +35,7 @@ trait ScannersCommon { // things to fill in, in addition to buf, decodeUni which come from CharArrayReader def error(off: Offset, msg: String): Unit def incompleteInputError(off: Offset, msg: String): Unit - def deprecationWarning(off: Offset, msg: String): Unit + def deprecationWarning(off: Offset, msg: String, since: String): Unit } def createKeywordArray(keywords: Seq[(Name, Token)], defaultToken: Token): (Token, Array[Token]) = { @@ -208,7 +208,7 @@ trait Scanners extends ScannersCommon { if (name == nme.MACROkw) syntaxError(s"$name is now a reserved word; usage as an identifier is disallowed") else if (emitIdentifierDeprecationWarnings) - deprecationWarning(s"$name is now a reserved word; usage as an identifier is deprecated") + deprecationWarning(s"$name is a reserved word (since 2.10.0); usage as an identifier is deprecated", "2.10.0") } } } @@ -824,7 +824,7 @@ trait Scanners extends ScannersCommon { if (settings.future) syntaxError(start, msg("unsupported")) else - deprecationWarning(start, msg("deprecated")) + deprecationWarning(start, msg("deprecated"), "2.11.0") putChar(oct.toChar) } else { ch match { @@ -1034,7 +1034,7 @@ trait Scanners extends ScannersCommon { /** generate an error at the current token offset */ def syntaxError(msg: String): Unit = syntaxError(offset, msg) - def deprecationWarning(msg: String): Unit = deprecationWarning(offset, msg) + def deprecationWarning(msg: String, since: String): Unit = deprecationWarning(offset, msg, since) /** signal an error where the input ended in the middle of a token */ def incompleteInputError(msg: String): Unit = { @@ -1204,8 +1204,8 @@ trait Scanners extends ScannersCommon { override val decodeUni: Boolean = !settings.nouescape // suppress warnings, throw exception on errors - def deprecationWarning(off: Offset, msg: String): Unit = () - def error (off: Offset, msg: String): Unit = throw new MalformedInput(off, msg) + def deprecationWarning(off: Offset, msg: String, since: String): Unit = () + def error(off: Offset, msg: String): Unit = throw new MalformedInput(off, msg) def incompleteInputError(off: Offset, msg: String): Unit = throw new MalformedInput(off, msg) } @@ -1214,9 +1214,9 @@ trait Scanners extends ScannersCommon { class UnitScanner(val unit: CompilationUnit, patches: List[BracePatch]) extends SourceFileScanner(unit.source) { def this(unit: CompilationUnit) = this(unit, List()) - override def deprecationWarning(off: Offset, msg: String) = currentRun.reporting.deprecationWarning(unit.position(off), msg) - override def error (off: Offset, msg: String) = reporter.error(unit.position(off), msg) - override def incompleteInputError(off: Offset, msg: String) = currentRun.parsing.incompleteInputError(unit.position(off), msg) + override def deprecationWarning(off: Offset, msg: String, since: String) = currentRun.reporting.deprecationWarning(unit.position(off), msg, since) + override def error(off: Offset, msg: String) = reporter.error(unit.position(off), msg) + override def incompleteInputError(off: Offset, msg: String) = currentRun.parsing.incompleteInputError(unit.position(off), msg) private var bracePatches: List[BracePatch] = patches diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index cc851b633089..fd9c99a3b966 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -27,7 +27,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { def freshName(prefix: String): Name = freshTermName(prefix) def freshTermName(prefix: String): TermName = unit.freshTermName(prefix) def freshTypeName(prefix: String): TypeName = unit.freshTypeName(prefix) - def deprecationWarning(off: Int, msg: String) = currentRun.reporting.deprecationWarning(off, msg) + def deprecationWarning(off: Int, msg: String, since: String) = currentRun.reporting.deprecationWarning(off, msg, since) implicit def i2p(offset : Int) : Position = Position.offset(unit.source, offset) def warning(pos : Int, msg : String) : Unit = reporter.warning(pos, msg) def syntaxError(pos: Int, msg: String) : Unit = reporter.error(pos, msg) diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index ac86dfd66510..c74a6938c6dd 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -860,9 +860,9 @@ trait JavaScanners extends ast.parser.ScannersCommon { class JavaUnitScanner(unit: CompilationUnit) extends JavaScanner { in = new JavaCharArrayReader(unit.source.content, !settings.nouescape.value, syntaxError) init() - def error (pos: Int, msg: String) = reporter.error(pos, msg) + def error(pos: Int, msg: String) = reporter.error(pos, msg) def incompleteInputError(pos: Int, msg: String) = currentRun.parsing.incompleteInputError(pos, msg) - def deprecationWarning(pos: Int, msg: String) = currentRun.reporting.deprecationWarning(pos, msg) + def deprecationWarning(pos: Int, msg: String, since: String) = currentRun.reporting.deprecationWarning(pos, msg, since) implicit def g2p(pos: Int): Position = Position.offset(unit.source, pos) } } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala index d4f44303bbde..2c1fb064cc00 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala @@ -148,7 +148,7 @@ trait ScalacPatternExpanders { val tupled = extractor.asSinglePattern if (effectivePatternArity(args) == 1 && isTupleType(extractor.typeOfSinglePattern)) { val sym = sel.symbol.owner - currentRun.reporting.deprecationWarning(sel.pos, sym, s"${sym} expects $productArity patterns$acceptMessage but crushing into $productArity-tuple to fit single pattern (SI-6675)") + currentRun.reporting.deprecationWarning(sel.pos, sym, s"${sym} expects $productArity patterns$acceptMessage but crushing into $productArity-tuple to fit single pattern (SI-6675)", "2.11.0") } tupled } else extractor diff --git a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala index 46561de78f13..57de44a038a1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala @@ -77,7 +77,7 @@ trait Adaptations { val msg = "Adaptation of argument list by inserting () is deprecated: " + ( if (isLeakyTarget) "leaky (Object-receiving) target makes this especially dangerous." else "this is unlikely to be what you want.") - context.deprecationWarning(t.pos, t.symbol, adaptWarningMessage(msg)) + context.deprecationWarning(t.pos, t.symbol, adaptWarningMessage(msg), "2.11.0") } } else if (settings.warnAdaptedArgs) context.warning(t.pos, adaptWarningMessage(s"Adapting argument list by creating a ${args.size}-tuple: this may not be what you want.")) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index bcc1ed3e645c..16ef75c8639d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -586,8 +586,8 @@ trait Contexts { self: Analyzer => } - def deprecationWarning(pos: Position, sym: Symbol, msg: String): Unit = - currentRun.reporting.deprecationWarning(fixPosition(pos), sym, msg) + def deprecationWarning(pos: Position, sym: Symbol, msg: String, since: String): Unit = + currentRun.reporting.deprecationWarning(fixPosition(pos), sym, msg, since) def deprecationWarning(pos: Position, sym: Symbol): Unit = currentRun.reporting.deprecationWarning(fixPosition(pos), sym) // TODO: allow this to escalate to an error, and implicit search will ignore deprecated implicits diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index d7405c28d532..ab6837ec0146 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -559,21 +559,22 @@ trait NamesDefaults { self: Analyzer => def removeNames(typer: Typer)(args: List[Tree], params: List[Symbol]): (List[Tree], Array[Int]) = { implicit val context0 = typer.context def matchesName(param: Symbol, name: Name, argIndex: Int) = { - def warn(w: String) = context0.deprecationWarning(args(argIndex).pos, param, w) + def warn(msg: String, since: String) = context0.deprecationWarning(args(argIndex).pos, param, msg, since) def checkDeprecation(anonOK: Boolean) = when (param.deprecatedParamName) { case Some(`name`) => true case Some(nme.NO_NAME) => anonOK } - def since = param.deprecatedParamVersion.map(ver => s" (since $ver)").getOrElse("") + def version = param.deprecatedParamVersion.getOrElse("") + def since = if (version.isEmpty) version else s" (since $version)" def checkName = { val res = param.name == name - if (res && checkDeprecation(true)) warn(s"naming parameter $name is deprecated$since.") + if (res && checkDeprecation(true)) warn(s"naming parameter $name is deprecated$since.", version) res } def checkAltName = { val res = checkDeprecation(false) - if (res) warn(s"the parameter name $name is deprecated$since: use ${param.name} instead") + if (res) warn(s"the parameter name $name is deprecated$since: use ${param.name} instead", version) res } !param.isSynthetic && (checkName || checkAltName) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 3aea64a1f277..2d454c2fe6cd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -548,10 +548,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def checkOverrideDeprecated() { if (other.hasDeprecatedOverridingAnnotation && !member.ownerChain.exists(x => x.isDeprecated || x.hasBridgeAnnotation)) { - val version = other.deprecatedOverridingVersion map (ver => s" (since $ver)") getOrElse "" - val message = other.deprecatedOverridingMessage map (msg => s": $msg") getOrElse "" - val report = s"overriding ${other.fullLocationString} is deprecated$version$message" - currentRun.reporting.deprecationWarning(member.pos, other, report) + val version = other.deprecatedOverridingVersion.getOrElse("") + val since = if (version.isEmpty) version else s" (since $version)" + val message = other.deprecatedOverridingMessage map (msg => s": $msg") getOrElse "" + val report = s"overriding ${other.fullLocationString} is deprecated$since$message" + currentRun.reporting.deprecationWarning(member.pos, other, report, version) } } } @@ -1423,7 +1424,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans currentRun.reporting.deprecationWarning( tree.pos, symbol, - s"${symbol.toString} overrides concrete, non-deprecated symbol(s): ${concrOvers.map(_.name.decode).mkString(", ")}") + s"${symbol.toString} overrides concrete, non-deprecated symbol(s): ${concrOvers.map(_.name.decode).mkString(", ")}", "") } } private def isRepeatedParamArg(tree: Tree) = currentApplication match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d44a0eaf59fd..dcf14612c9c8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1704,10 +1704,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (!isPastTyper && psym.hasDeprecatedInheritanceAnnotation && !sameSourceFile && !context.owner.ownerChain.exists(x => x.isDeprecated || x.hasBridgeAnnotation)) { - val version = psym.deprecatedInheritanceVersion map (ver => s" (since $ver)") getOrElse "" - val message = psym.deprecatedInheritanceMessage map (msg => s": $msg") getOrElse "" - val report = s"inheritance from ${psym.fullLocationString} is deprecated$version$message" - context.deprecationWarning(parent.pos, psym, report) + val version = psym.deprecatedInheritanceVersion.getOrElse("") + val since = if (version.isEmpty) version else s" (since $version)" + val message = psym.deprecatedInheritanceMessage.map(msg => s": $msg").getOrElse("") + val report = s"inheritance from ${psym.fullLocationString} is deprecated$since$message" + context.deprecationWarning(parent.pos, psym, report, version) } if (psym.isSealed && !phase.erasedTypes) @@ -3710,7 +3711,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } if (annType.typeSymbol == DeprecatedAttr && argss.flatten.size < 2) - context.deprecationWarning(ann.pos, DeprecatedAttr, "@deprecated now takes two arguments; see the scaladoc.") + context.deprecationWarning(ann.pos, DeprecatedAttr, "@deprecated now takes two arguments; see the scaladoc.", "2.11.0") if ((typedAnn.tpe == null) || typedAnn.tpe.isErroneous) ErroneousAnnotation else annInfo(typedAnn) @@ -4785,7 +4786,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // temporarily use `filter` as an alternative for `withFilter` def tryWithFilterAndFilter(tree: Select, qual: Tree): Tree = { - def warn(sym: Symbol) = context.deprecationWarning(tree.pos, sym, s"`withFilter' method does not yet exist on ${qual.tpe.widen}, using `filter' method instead") + def warn(sym: Symbol) = context.deprecationWarning(tree.pos, sym, s"`withFilter' method does not yet exist on ${qual.tpe.widen}, using `filter' method instead", "2.11.0") silent(_ => typedSelect(tree, qual, nme.withFilter)) orElse { _ => silent(_ => typed1(Select(qual, nme.filter) setPos tree.pos, mode, pt)) match { case SilentResultValue(res) => warn(res.symbol) ; res @@ -5580,7 +5581,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } def reportWarning(inferredType: Type) = { val explanation = s"inference of $inferredType from macro impl's c.Expr[$inferredType] is deprecated and is going to stop working in 2.12" - context.deprecationWarning(ddef.pos, ddef.symbol, s"$commonMessage ($explanation)") + context.deprecationWarning(ddef.pos, ddef.symbol, s"$commonMessage ($explanation)", "2.12.0") } computeMacroDefTypeFromMacroImplRef(ddef, rhs1) match { case ErrorType => ErrorType diff --git a/src/compiler/scala/tools/reflect/FormatInterpolator.scala b/src/compiler/scala/tools/reflect/FormatInterpolator.scala index cbdb01a10a95..9825acd39fd7 100644 --- a/src/compiler/scala/tools/reflect/FormatInterpolator.scala +++ b/src/compiler/scala/tools/reflect/FormatInterpolator.scala @@ -117,7 +117,7 @@ abstract class FormatInterpolator { c.error(errPoint, msg("unsupported")) s0 } else { - currentRun.reporting.deprecationWarning(errPoint, msg("deprecated")) + currentRun.reporting.deprecationWarning(errPoint, msg("deprecated"), "2.11.0") try StringContext.treatEscapes(s0) catch escapeHatch } } diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 36e2fa25dd2e..0c24d17c1539 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -80,7 +80,8 @@ extends scala.collection.AbstractSeq[Int] || (start < end && step < 0) || (start == end && !isInclusive) ) - @deprecated("this method will be made private, use `length` instead.", "2.11") + + @deprecated("this method will be made private, use `length` instead", "2.11.0") final val numRangeElements: Int = { if (step == 0) throw new IllegalArgumentException("step cannot be 0.") else if (isEmpty) 0 @@ -90,7 +91,8 @@ extends scala.collection.AbstractSeq[Int] else len.toInt } } - @deprecated("this method will be made private, use `last` instead.", "2.11") + + @deprecated("this method will be made private, use `last` instead", "2.11.0") final val lastElement = if (isEmpty) start - step else step match { @@ -103,7 +105,7 @@ extends scala.collection.AbstractSeq[Int] else end - step } - @deprecated("this method will be made private.", "2.11") + @deprecated("this method will be made private", "2.11.0") final val terminalElement = lastElement + step /** The last element of this range. This method will return the correct value diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index f2c3284f9236..fe684e4d46fb 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -87,7 +87,7 @@ trait ExecutionContext { * constructed, so that it doesn't need any additional * preparation later. */ - @deprecated("preparation of ExecutionContexts will be removed", "2.12") + @deprecated("preparation of ExecutionContexts will be removed", "2.12.0") def prepare(): ExecutionContext = this } diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index 93e9fddcb3a8..c0398605a6fd 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -113,7 +113,7 @@ trait Future[+T] extends Awaitable[T] { * * @group Callbacks */ - @deprecated("use `foreach` or `onComplete` instead (keep in mind that they take total rather than partial functions)", "2.12") + @deprecated("use `foreach` or `onComplete` instead (keep in mind that they take total rather than partial functions)", "2.12.0") def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit = onComplete { case Success(v) => pf.applyOrElse[T, Any](v, Predef.conforms[T]) // Exploiting the cached function to avoid MatchError @@ -138,7 +138,7 @@ trait Future[+T] extends Awaitable[T] { * * @group Callbacks */ - @deprecated("use `onComplete` or `failed.foreach` instead (keep in mind that they take total rather than partial functions)", "2.12") + @deprecated("use `onComplete` or `failed.foreach` instead (keep in mind that they take total rather than partial functions)", "2.12.0") def onFailure[U](@deprecatedName('callback) pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit = onComplete { case Failure(t) => pf.applyOrElse[Throwable, Any](t, Predef.conforms[Throwable]) // Exploiting the cached function to avoid MatchError @@ -688,7 +688,7 @@ object Future { * @param p the predicate which indicates if it's a match * @return the `Future` holding the optional result of the search */ - @deprecated("use the overloaded version of this method that takes a scala.collection.immutable.Iterable instead", "2.12") + @deprecated("use the overloaded version of this method that takes a scala.collection.immutable.Iterable instead", "2.12.0") def find[T](@deprecatedName('futurestravonce) futures: TraversableOnce[Future[T]])(@deprecatedName('predicate) p: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]] = { val futuresBuffer = futures.toBuffer if (futuresBuffer.isEmpty) successful[Option[T]](None) @@ -775,7 +775,7 @@ object Future { * @param op the fold operation to be applied to the zero and futures * @return the `Future` holding the result of the fold */ - @deprecated("use Future.foldLeft instead", "2.12") + @deprecated("use Future.foldLeft instead", "2.12.0") def fold[T, R](futures: TraversableOnce[Future[T]])(zero: R)(@deprecatedName('foldFun) op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = { if (futures.isEmpty) successful(zero) else sequence(futures).map(_.foldLeft(zero)(op)) @@ -794,7 +794,7 @@ object Future { * @param op the reduce operation which is applied to the results of the futures * @return the `Future` holding the result of the reduce */ - @deprecated("use Future.reduceLeft instead", "2.12") + @deprecated("use Future.reduceLeft instead", "2.12.0") def reduce[T, R >: T](futures: TraversableOnce[Future[T]])(op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = { if (futures.isEmpty) failed(new NoSuchElementException("reduce attempted on empty collection")) else sequence(futures).map(_ reduceLeft op) diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index 8e03017f0964..4bc0c0cf950d 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -148,7 +148,7 @@ object BigDecimal { * @param mc the `MathContext` used for future computations * @return the constructed `BigDecimal` */ - @deprecated("MathContext is not applied to Doubles in valueOf. Use BigDecimal.decimal to use rounding, or java.math.BigDecimal.valueOf to avoid it.", "2.11") + @deprecated("MathContext is not applied to Doubles in valueOf. Use BigDecimal.decimal to use rounding, or java.math.BigDecimal.valueOf to avoid it.", "2.11.0") def valueOf(d: Double, mc: MathContext): BigDecimal = apply(BigDec valueOf d, mc) /** Constructs a `BigDecimal` using the java BigDecimal static @@ -163,14 +163,14 @@ object BigDecimal { * valueOf constructor. This is unlikely to do what you want; * use `valueOf(f.toDouble)` or `decimal(f)` instead. */ - @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).", "2.11") + @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).", "2.11.0") def valueOf(f: Float): BigDecimal = valueOf(f.toDouble) /** Constructs a `BigDecimal` using the java BigDecimal static * valueOf constructor. This is unlikely to do what you want; * use `valueOf(f.toDouble)` or `decimal(f)` instead. */ - @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).", "2.11") + @deprecated("Float arguments to valueOf may not do what you wish. Use decimal or valueOf(f.toDouble).", "2.11.0") def valueOf(f: Float, mc: MathContext): BigDecimal = valueOf(f.toDouble, mc) @@ -259,10 +259,10 @@ object BigDecimal { */ def apply(d: Double, mc: MathContext): BigDecimal = decimal(d, mc) - @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11") + @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11.0") def apply(x: Float): BigDecimal = apply(x.toDouble) - @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11") + @deprecated("The default conversion from Float may not do what you want. Use BigDecimal.decimal for a String representation, or explicitly convert the Float with .toDouble.", "2.11.0") def apply(x: Float, mc: MathContext): BigDecimal = apply(x.toDouble, mc) /** Translates a character array representation of a `BigDecimal` @@ -329,7 +329,7 @@ object BigDecimal { /** Constructs a `BigDecimal` from a `java.math.BigDecimal`. */ def apply(bd: BigDec): BigDecimal = apply(bd, defaultMathContext) - @deprecated("This method appears to round a java.math.BigDecimal but actually doesn't. Use new BigDecimal(bd, mc) instead for no rounding, or BigDecimal.decimal(bd, mc) for rounding.", "2.11") + @deprecated("This method appears to round a java.math.BigDecimal but actually doesn't. Use new BigDecimal(bd, mc) instead for no rounding, or BigDecimal.decimal(bd, mc) for rounding.", "2.11.0") def apply(bd: BigDec, mc: MathContext): BigDecimal = new BigDecimal(bd, mc) /** Implicit conversion from `Int` to `BigDecimal`. */ @@ -467,7 +467,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ * `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat`, depending on the intended meaning. * By default, `decimal` creation is used, so `isDecimalFloat` is probably what you want. */ - @deprecated("What constitutes validity is unclear. Use `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat` instead.", "2.11") + @deprecated("What constitutes validity is unclear. Use `isExactFloat`, `isBinaryFloat`, or `isDecimalFloat` instead.", "2.11.0") def isValidFloat = { val f = toFloat !f.isInfinity && bigDecimal.compareTo(new BigDec(f.toDouble)) == 0 @@ -476,7 +476,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ * `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble`, depending on the intended meaning. * By default, `decimal` creation is used, so `isDecimalDouble` is probably what you want. */ - @deprecated("Validity has distinct meanings. Use `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble` instead.", "2.11") + @deprecated("Validity has distinct meanings. Use `isExactDouble`, `isBinaryDouble`, or `isDecimalDouble` instead.", "2.11.0") def isValidDouble = { val d = toDouble !d.isInfinity && bigDecimal.compareTo(new BigDec(d)) == 0 diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala index 3c8b21b03c1c..00e9585c38e2 100644 --- a/src/library/scala/util/Try.scala +++ b/src/library/scala/util/Try.scala @@ -132,7 +132,7 @@ sealed abstract class Try[+T] extends Product with Serializable { * collection" contract even though it seems unlikely to matter much in a * collection with max size 1. */ - @deprecatedInheritance("You were never supposed to be able to extend this class.", "2.12") + @deprecatedInheritance("You were never supposed to be able to extend this class.", "2.12.0") class WithFilter(p: T => Boolean) { def map[U](f: T => U): Try[U] = Try.this filter p map f def flatMap[U](f: T => Try[U]): Try[U] = Try.this filter p flatMap f diff --git a/src/reflect/scala/reflect/internal/Reporting.scala b/src/reflect/scala/reflect/internal/Reporting.scala index afdae8128946..27fda9a7d453 100644 --- a/src/reflect/scala/reflect/internal/Reporting.scala +++ b/src/reflect/scala/reflect/internal/Reporting.scala @@ -25,7 +25,7 @@ trait Reporting { self : Positions => type PerRunReporting <: PerRunReportingBase protected def PerRunReporting: PerRunReporting abstract class PerRunReportingBase { - def deprecationWarning(pos: Position, msg: String): Unit + def deprecationWarning(pos: Position, msg: String, since: String): Unit /** Have we already supplemented the error message of a compiler crash? */ private[this] var supplementedError = false diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala index 8d74065207e1..69bade55f1a5 100644 --- a/src/reflect/scala/reflect/internal/Variances.scala +++ b/src/reflect/scala/reflect/internal/Variances.scala @@ -79,7 +79,7 @@ trait Variances { // Unsound pre-2.11 behavior preserved under -Xsource:2.10 if (settings.isScala211 || sym.isOverridingSymbol) Invariant else { - currentRun.reporting.deprecationWarning(sym.pos, s"Construct depends on unsound variance analysis and will not compile in scala 2.11 and beyond") + currentRun.reporting.deprecationWarning(sym.pos, "Construct depends on unsound variance analysis and will not compile in scala 2.11 and beyond", "2.11.0") Bivariant } ) diff --git a/src/reflect/scala/reflect/internal/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala index efb8126ff013..79195e6eab5c 100644 --- a/src/reflect/scala/reflect/internal/util/StringOps.scala +++ b/src/reflect/scala/reflect/internal/util/StringOps.scala @@ -72,12 +72,12 @@ trait StringOps { */ def countElementsAsString(n: Int, elements: String): String = n match { - case 0 => "no " + elements + "s" + case 0 => s"no ${elements}s" case 1 => "one " + elements case 2 => "two " + elements + "s" case 3 => "three " + elements + "s" case 4 => "four " + elements + "s" - case _ => "" + n + " " + elements + "s" + case _ => s"$n ${elements}s" } /** Turns a count into a friendly English description if n<=4. diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala index 7848753e6911..a87d1d23cc38 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala @@ -30,7 +30,7 @@ class JavaUniverse extends InternalSymbolTable with JavaUniverseForce with Refle // minimal Run to get Reporting wired def currentRun = new RunReporting {} class PerRunReporting extends PerRunReportingBase { - def deprecationWarning(pos: Position, msg: String): Unit = reporter.warning(pos, msg) + def deprecationWarning(pos: Position, msg: String, since: String): Unit = reporter.warning(pos, msg) } protected def PerRunReporting = new PerRunReporting diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index a77e6f45f8fb..763a8ccd1bc7 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -780,7 +780,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } ((pos, msg)) :: loop(filtered) } - val warnings = loop(run.reporting.allConditionalWarnings) + val warnings = loop(run.reporting.allConditionalWarnings.map{case (pos, (msg, since)) => (pos, msg)}) if (warnings.nonEmpty) mostRecentWarnings = warnings } diff --git a/test/files/jvm/future-spec.check b/test/files/jvm/future-spec.check index 50c5d446af97..562d699bde8e 100644 --- a/test/files/jvm/future-spec.check +++ b/test/files/jvm/future-spec.check @@ -1 +1,3 @@ -warning: there were 20 deprecation warnings; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0) +warning: there were 19 deprecation warnings (since 2.12.0) +warning: there were 20 deprecation warnings in total; re-run with -deprecation for details diff --git a/test/files/jvm/scala-concurrent-tck.check b/test/files/jvm/scala-concurrent-tck.check index 8aec46e5d636..88cff75abba9 100644 --- a/test/files/jvm/scala-concurrent-tck.check +++ b/test/files/jvm/scala-concurrent-tck.check @@ -1 +1 @@ -warning: there were 75 deprecation warnings; re-run with -deprecation for details +warning: there were 75 deprecation warnings (since 2.12.0); re-run with -deprecation for details diff --git a/test/files/jvm/serialization-new.check b/test/files/jvm/serialization-new.check index ca91ec107384..5b8a08da82e0 100644 --- a/test/files/jvm/serialization-new.check +++ b/test/files/jvm/serialization-new.check @@ -1,4 +1,6 @@ -warning: there were three deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0) +warning: there was one deprecation warning (since 2.11.6) +warning: there were three deprecation warnings in total; re-run with -deprecation for details a1 = Array[1,2,3] _a1 = Array[1,2,3] arrayEquals(a1, _a1): true diff --git a/test/files/jvm/serialization.check b/test/files/jvm/serialization.check index ca91ec107384..5b8a08da82e0 100644 --- a/test/files/jvm/serialization.check +++ b/test/files/jvm/serialization.check @@ -1,4 +1,6 @@ -warning: there were three deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0) +warning: there was one deprecation warning (since 2.11.6) +warning: there were three deprecation warnings in total; re-run with -deprecation for details a1 = Array[1,2,3] _a1 = Array[1,2,3] arrayEquals(a1, _a1): true diff --git a/test/files/neg/checksensible.check b/test/files/neg/checksensible.check index 7de22fef5475..a6e9176c6954 100644 --- a/test/files/neg/checksensible.check +++ b/test/files/neg/checksensible.check @@ -97,7 +97,7 @@ checksensible.scala:84: warning: comparing values of types EqEqRefTest.this.C3 a checksensible.scala:95: warning: comparing values of types Unit and Int using `!=' will always yield true while ((c = in.read) != -1) ^ -warning: there were three deprecation warnings; re-run with -deprecation for details +warning: there were three deprecation warnings (since 2.11.0); re-run with -deprecation for details error: No warnings can be incurred under -Xfatal-warnings. 34 warnings found one error found diff --git a/test/files/neg/t7783.check b/test/files/neg/t7783.check index 18dc84a8dbe5..647cfee12152 100644 --- a/test/files/neg/t7783.check +++ b/test/files/neg/t7783.check @@ -1,16 +1,16 @@ -t7783.scala:1: warning: type D in object O is deprecated (since ): +t7783.scala:1: warning: type D in object O is deprecated: object O { class C; @deprecated("", "") type D = C; def foo: Seq[D] = Nil } ^ -t7783.scala:11: warning: type D in object O is deprecated (since ): +t7783.scala:11: warning: type D in object O is deprecated: type T = O.D ^ -t7783.scala:12: warning: type D in object O is deprecated (since ): +t7783.scala:12: warning: type D in object O is deprecated: locally(null: O.D) ^ -t7783.scala:13: warning: type D in object O is deprecated (since ): +t7783.scala:13: warning: type D in object O is deprecated: val x: O.D = null ^ -t7783.scala:14: warning: type D in object O is deprecated (since ): +t7783.scala:14: warning: type D in object O is deprecated: locally(null.asInstanceOf[O.D]) ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/run/bitsets.check b/test/files/run/bitsets.check index c24fd6238f98..770d9b5e3ffe 100644 --- a/test/files/run/bitsets.check +++ b/test/files/run/bitsets.check @@ -1,4 +1,4 @@ -warning: there were three deprecation warnings; re-run with -deprecation for details +warning: there were three deprecation warnings (since 2.11.6); re-run with -deprecation for details ms0 = BitSet(2) ms1 = BitSet(2) ms2 = BitSet(2) diff --git a/test/files/run/collection-stacks.check b/test/files/run/collection-stacks.check index 3a366bfcdfd9..826e3a87f835 100644 --- a/test/files/run/collection-stacks.check +++ b/test/files/run/collection-stacks.check @@ -1,4 +1,4 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details 3-2-1: true 3-2-1: true apply diff --git a/test/files/run/colltest.check b/test/files/run/colltest.check index 9579d781aac6..f362f23547ba 100644 --- a/test/files/run/colltest.check +++ b/test/files/run/colltest.check @@ -1,4 +1,4 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0); re-run with -deprecation for details true false true diff --git a/test/files/run/delay-bad.check b/test/files/run/delay-bad.check index cb6e329f7ac8..fcd05c827f06 100644 --- a/test/files/run/delay-bad.check +++ b/test/files/run/delay-bad.check @@ -4,7 +4,7 @@ delay-bad.scala:53: warning: a pure expression does nothing in statement positio delay-bad.scala:73: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses f(new { val x = 5 } with E() { 5 }) ^ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details // new C { } diff --git a/test/files/run/future-flatmap-exec-count.check b/test/files/run/future-flatmap-exec-count.check index 7065c133e028..7c68bd76b5d6 100644 --- a/test/files/run/future-flatmap-exec-count.check +++ b/test/files/run/future-flatmap-exec-count.check @@ -1,4 +1,4 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.12.0); re-run with -deprecation for details mapping execute() flatmapping diff --git a/test/files/run/reflection-java-annotations.check b/test/files/run/reflection-java-annotations.check index 842037254ef8..67317d20729e 100644 --- a/test/files/run/reflection-java-annotations.check +++ b/test/files/run/reflection-java-annotations.check @@ -1,4 +1,4 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details List(JavaComplexAnnotation_1(v1 = 1, v10 = "hello", v101 = [101, 101], v102 = [102, 102], v103 = ['g', 'g'], v104 = [104, 104], v105 = [105L, 105L], v106 = [106.0, 106.0], v107 = [107.0, 107.0], v108 = [false, true], v11 = classOf[JavaAnnottee_1], v110 = ["hello", "world"], v111 = [classOf[JavaSimpleAnnotation_1], classOf[JavaComplexAnnotation_1]], v112 = [FOO, BAR], v113 = [JavaSimpleAnnotation_1(v1 = 21, v10 = "world2", v11 = classOf[JavaComplexAnnotation_1], v12 = BAR, v2 = 22, v3 = '\027', v4 = 24, v5 = 25L, v6 = 26.0, v7 = 27.0, v8 = false)], v12 = FOO, v13 = JavaSimpleAnnotation_1(v1 = 11, v10 = "world1", v11 = classOf[JavaSimpleAnnotation_1], v12 = FOO, v2 = 12, v3 = '\r', v4 = 14, v5 = 15L, v6 = 16.0, v7 = 17.0, v8 = false), v2 = 2, v3 = '\03', v4 = 4, v5 = 5L, v6 = 6.0, v7 = 7.0, v8 = false)) ======= new JavaComplexAnnotation_1(v1 = 1, v10 = "hello", v101 = Array(101, 101), v102 = Array(102, 102), v103 = Array('g', 'g'), v104 = Array(104, 104), v105 = Array(105L, 105L), v106 = Array(106.0, 106.0), v107 = Array(107.0, 107.0), v108 = Array(false, true), v11 = classOf[JavaAnnottee_1], v110 = Array("hello", "world"), v111 = Array(classOf[JavaSimpleAnnotation_1], classOf[JavaComplexAnnotation_1]), v112 = Array(FOO, BAR), v113 = Array(new JavaSimpleAnnotation_1(v1 = 21, v10 = "world2", v11 = classOf[JavaComplexAnnotation_1], v12 = BAR, v2 = 22, v3 = '\027', v4 = 24, v5 = 25L, v6 = 26.0, v7 = 27.0, v8 = false)), v12 = FOO, v13 = new JavaSimpleAnnotation_1(v1 = 11, v10 = "world1", v11 = classOf[JavaSimpleAnnotation_1], v12 = FOO, v2 = 12, v3 = '\r', v4 = 14, v5 = 15L, v6 = 16.0, v7 = 17.0, v8 = false), v2 = 2, v3 = '\03', v4 = 4, v5 = 5L, v6 = 6.0, v7 = 7.0, v8 = false) diff --git a/test/files/run/repl-no-imports-no-predef-power.check b/test/files/run/repl-no-imports-no-predef-power.check index 0d4a30b8e3b3..a76db3dbc2cb 100644 --- a/test/files/run/repl-no-imports-no-predef-power.check +++ b/test/files/run/repl-no-imports-no-predef-power.check @@ -7,7 +7,7 @@ Try :help or completions for vals._ and power._ scala> // guarding against "error: reference to global is ambiguous" scala> global.emptyValDef // "it is imported twice in the same scope by ..." -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details res0: $r.global.noSelfType.type = private val _ = _ scala> val tp = ArrayClass[scala.util.Random] // magic with tags diff --git a/test/files/run/repl-power.check b/test/files/run/repl-power.check index 0d4a30b8e3b3..a76db3dbc2cb 100644 --- a/test/files/run/repl-power.check +++ b/test/files/run/repl-power.check @@ -7,7 +7,7 @@ Try :help or completions for vals._ and power._ scala> // guarding against "error: reference to global is ambiguous" scala> global.emptyValDef // "it is imported twice in the same scope by ..." -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details res0: $r.global.noSelfType.type = private val _ = _ scala> val tp = ArrayClass[scala.util.Random] // magic with tags diff --git a/test/files/run/richs.check b/test/files/run/richs.check index cf265ae00738..97b032393c6a 100644 --- a/test/files/run/richs.check +++ b/test/files/run/richs.check @@ -1,4 +1,4 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0); re-run with -deprecation for details RichCharTest1: true diff --git a/test/files/run/sbt-icode-interface.check b/test/files/run/sbt-icode-interface.check index df1629dd7eb1..7421f077f62a 100644 --- a/test/files/run/sbt-icode-interface.check +++ b/test/files/run/sbt-icode-interface.check @@ -1 +1 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.12.0); re-run with -deprecation for details diff --git a/test/files/run/t2212.check b/test/files/run/t2212.check index 1465f1341aa2..d13ea43b0747 100644 --- a/test/files/run/t2212.check +++ b/test/files/run/t2212.check @@ -1,4 +1,4 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0); re-run with -deprecation for details LinkedList(1) LinkedList(1) true diff --git a/test/files/run/t3361.check b/test/files/run/t3361.check index 5e0a76350199..7d2fa3b1559b 100644 --- a/test/files/run/t3361.check +++ b/test/files/run/t3361.check @@ -1 +1 @@ -warning: there were 16 deprecation warnings; re-run with -deprecation for details +warning: there were 16 deprecation warnings (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t3647.check b/test/files/run/t3647.check index e5c1ee17013e..cb16c6486f84 100644 --- a/test/files/run/t3647.check +++ b/test/files/run/t3647.check @@ -1 +1 @@ -warning: there were three deprecation warnings; re-run with -deprecation for details +warning: there were three deprecation warnings (since 2.11.8); re-run with -deprecation for details diff --git a/test/files/run/t3888.check b/test/files/run/t3888.check index df1629dd7eb1..6fda32d713ea 100644 --- a/test/files/run/t3888.check +++ b/test/files/run/t3888.check @@ -1 +1 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t3970.check b/test/files/run/t3970.check index 0683a6c1a689..fd1c3af3bb92 100644 --- a/test/files/run/t3970.check +++ b/test/files/run/t3970.check @@ -1 +1 @@ -warning: there were 5 deprecation warnings; re-run with -deprecation for details +warning: there were 5 deprecation warnings (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t3996.check b/test/files/run/t3996.check index a9ecc29fea08..f214cd8e6a65 100644 --- a/test/files/run/t3996.check +++ b/test/files/run/t3996.check @@ -1 +1 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t4080.check b/test/files/run/t4080.check index 462e925b7694..18f18ef2ddab 100644 --- a/test/files/run/t4080.check +++ b/test/files/run/t4080.check @@ -1,2 +1,2 @@ -warning: there were three deprecation warnings; re-run with -deprecation for details +warning: there were three deprecation warnings (since 2.11.0); re-run with -deprecation for details LinkedList(1, 0, 2, 3) diff --git a/test/files/run/t4396.check b/test/files/run/t4396.check index d38fb7fae7ec..9eb1be0255a6 100644 --- a/test/files/run/t4396.check +++ b/test/files/run/t4396.check @@ -1,4 +1,4 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details hallo constructor out:22 diff --git a/test/files/run/t4461.check b/test/files/run/t4461.check index 346993af6f48..32c7f5c4873c 100644 --- a/test/files/run/t4461.check +++ b/test/files/run/t4461.check @@ -1,4 +1,4 @@ -warning: there were four deprecation warnings; re-run with -deprecation for details +warning: there were four deprecation warnings (since 2.11.0); re-run with -deprecation for details Include(End,1) Include(End,2) Include(End,3) diff --git a/test/files/run/t4594-repl-settings.scala b/test/files/run/t4594-repl-settings.scala index 8ececce24af3..524ec2884341 100644 --- a/test/files/run/t4594-repl-settings.scala +++ b/test/files/run/t4594-repl-settings.scala @@ -9,7 +9,7 @@ object Test extends SessionTest { |depp: String | |scala> def a = depp - |warning: there was one deprecation warning; re-run with -deprecation for details + |warning: there was one deprecation warning (since Time began.); re-run with -deprecation for details |a: String | |scala> :settings -deprecation diff --git a/test/files/run/t4680.check b/test/files/run/t4680.check index 21a1e0cd1505..21c5f9e56791 100644 --- a/test/files/run/t4680.check +++ b/test/files/run/t4680.check @@ -4,7 +4,7 @@ t4680.scala:51: warning: a pure expression does nothing in statement position; y t4680.scala:69: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses new { val x = 5 } with E() { 5 } ^ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details // new C { } diff --git a/test/files/run/t4813.check b/test/files/run/t4813.check index a9ecc29fea08..f214cd8e6a65 100644 --- a/test/files/run/t4813.check +++ b/test/files/run/t4813.check @@ -1 +1 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t5428.check b/test/files/run/t5428.check index 52fce0939968..d298f0ef102e 100644 --- a/test/files/run/t5428.check +++ b/test/files/run/t5428.check @@ -1,2 +1,2 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details Stack(8, 7, 6, 5, 4, 3) diff --git a/test/files/run/t576.check b/test/files/run/t576.check index 22f3843abfea..2934e395ba84 100644 --- a/test/files/run/t576.check +++ b/test/files/run/t576.check @@ -1,4 +1,4 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details 1 2 3 diff --git a/test/files/run/t6111.check b/test/files/run/t6111.check index 588065800198..99f9c551b254 100644 --- a/test/files/run/t6111.check +++ b/test/files/run/t6111.check @@ -1,3 +1,3 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0); re-run with -deprecation for details (8,8) (x,x) diff --git a/test/files/run/t6292.check b/test/files/run/t6292.check index 6f7430d5b866..f7b8f483ab94 100644 --- a/test/files/run/t6292.check +++ b/test/files/run/t6292.check @@ -1 +1 @@ -warning: there were 7 deprecation warnings; re-run with -deprecation for details +warning: there were 7 deprecation warnings (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t6329_repl.check b/test/files/run/t6329_repl.check index 8909c47e79c4..86cd984e117a 100644 --- a/test/files/run/t6329_repl.check +++ b/test/files/run/t6329_repl.check @@ -3,28 +3,28 @@ scala> import scala.reflect.classTag import scala.reflect.classTag scala> classManifest[scala.List[_]] -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.10.0); re-run with -deprecation for details res0: scala.reflect.ClassTag[List[_]] = scala.collection.immutable.List[] scala> classTag[scala.List[_]] res1: scala.reflect.ClassTag[List[_]] = scala.collection.immutable.List scala> classManifest[scala.collection.immutable.List[_]] -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.10.0); re-run with -deprecation for details res2: scala.reflect.ClassTag[List[_]] = scala.collection.immutable.List[] scala> classTag[scala.collection.immutable.List[_]] res3: scala.reflect.ClassTag[List[_]] = scala.collection.immutable.List scala> classManifest[Predef.Set[_]] -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.10.0); re-run with -deprecation for details res4: scala.reflect.ClassTag[scala.collection.immutable.Set[_]] = scala.collection.immutable.Set[] scala> classTag[Predef.Set[_]] res5: scala.reflect.ClassTag[scala.collection.immutable.Set[_]] = scala.collection.immutable.Set scala> classManifest[scala.collection.immutable.Set[_]] -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.10.0); re-run with -deprecation for details res6: scala.reflect.ClassTag[scala.collection.immutable.Set[_]] = scala.collection.immutable.Set[] scala> classTag[scala.collection.immutable.Set[_]] diff --git a/test/files/run/t6329_repl_bug.check b/test/files/run/t6329_repl_bug.check index 4b539f9e580f..6476fa71fc07 100644 --- a/test/files/run/t6329_repl_bug.check +++ b/test/files/run/t6329_repl_bug.check @@ -6,7 +6,7 @@ scala> import scala.reflect.runtime._ import scala.reflect.runtime._ scala> classManifest[List[_]] -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.10.0); re-run with -deprecation for details res0: scala.reflect.ClassTag[List[_]] = scala.collection.immutable.List[] scala> scala.reflect.classTag[List[_]] diff --git a/test/files/run/t6329_vanilla_bug.check b/test/files/run/t6329_vanilla_bug.check index 01bf0636ea13..4e139dd9544d 100644 --- a/test/files/run/t6329_vanilla_bug.check +++ b/test/files/run/t6329_vanilla_bug.check @@ -1,3 +1,3 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.10.0); re-run with -deprecation for details scala.collection.immutable.List[] scala.collection.immutable.List diff --git a/test/files/run/t6481.check b/test/files/run/t6481.check index 4a3f6f7ee944..0535110f7542 100644 --- a/test/files/run/t6481.check +++ b/test/files/run/t6481.check @@ -1,4 +1,4 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details delayed init new foo(1, 2) delayed init diff --git a/test/files/run/t6690.check b/test/files/run/t6690.check index a9ecc29fea08..f214cd8e6a65 100644 --- a/test/files/run/t6690.check +++ b/test/files/run/t6690.check @@ -1 +1 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t6863.check b/test/files/run/t6863.check index d4df5f7a74bc..010e82a41ef6 100644 --- a/test/files/run/t6863.check +++ b/test/files/run/t6863.check @@ -10,4 +10,4 @@ t6863.scala:46: warning: comparing values of types Unit and Unit using `==' will t6863.scala:59: warning: comparing values of types Unit and Unit using `==' will always yield true assert({ () => x }.apply == ()) ^ -warning: there were four deprecation warnings; re-run with -deprecation for details +warning: there were four deprecation warnings (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t6935.check b/test/files/run/t6935.check index df1629dd7eb1..6fda32d713ea 100644 --- a/test/files/run/t6935.check +++ b/test/files/run/t6935.check @@ -1 +1 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t8549.check b/test/files/run/t8549.check index a9ecc29fea08..f214cd8e6a65 100644 --- a/test/files/run/t8549.check +++ b/test/files/run/t8549.check @@ -1 +1 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/unittest_collection.check b/test/files/run/unittest_collection.check index df1629dd7eb1..6fda32d713ea 100644 --- a/test/files/run/unittest_collection.check +++ b/test/files/run/unittest_collection.check @@ -1 +1 @@ -warning: there was one deprecation warning; re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala index 8cc7aefdd34e..fb05ab8d5a2a 100644 --- a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala +++ b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala @@ -85,7 +85,7 @@ class SymbolTableForUnitTesting extends SymbolTable { // minimal Run to get Reporting wired def currentRun = new RunReporting {} class PerRunReporting extends PerRunReportingBase { - def deprecationWarning(pos: Position, msg: String): Unit = reporter.warning(pos, msg) + def deprecationWarning(pos: Position, msg: String, since: String): Unit = reporter.warning(pos, msg) } protected def PerRunReporting = new PerRunReporting From 85057d542c7e201191544415ff454afb243aa104 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Thu, 19 May 2016 18:46:49 +0200 Subject: [PATCH 073/153] Add documentation to @deprecated --- src/library/scala/deprecated.scala | 43 ++++++++++++++++++- src/library/scala/deprecatedInheritance.scala | 20 ++++++++- src/library/scala/deprecatedName.scala | 40 +++++++++-------- src/library/scala/deprecatedOverriding.scala | 19 ++++++++ 4 files changed, 101 insertions(+), 21 deletions(-) diff --git a/src/library/scala/deprecated.scala b/src/library/scala/deprecated.scala index e940a4bfbe2e..7338dffb8dd0 100644 --- a/src/library/scala/deprecated.scala +++ b/src/library/scala/deprecated.scala @@ -11,11 +11,52 @@ package scala import scala.annotation.meta._ /** An annotation that designates that a definition is deprecated. - * Access to the member then generates a deprecated warning. + * A deprecation warning is issued upon usage of the annotated definition. * + * Library authors should state the library's deprecation policy in their documentation to give + * developers guidance on how long a deprecated definition will be preserved. + * + * Library authors should prepend the name of their library to the version number to help + * developers distinguish deprecations coming from different libraries: + * + * {{{ + * @deprecated("this method will be removed", "FooLib 12.0") + * def oldMethod(x: Int) = ... + * }}} + * + * The compiler will emit deprecation warnings grouped by library and version: + * + * {{{ + * oldMethod(1) + * oldMethod(2) + * aDeprecatedMethodFromBarLibrary(3, 4) + * + * // warning: there were two deprecation warnings (since FooLib 12.0) + * // warning: there was one deprecation warning (since BarLib 3.2) + * // warning: there were three deprecation warnings in total; re-run with -deprecation for details + * }}} + * + * A deprecated element of the Scala language or a definition in the Scala standard library will + * be preserved or at least another major version. + * + * This means that an element deprecated since 2.12 will be preserved in 2.13 and will very likely + * not be part of 2.14, though sometimes a deprecated element might be kept for more than a major + * release to ease migration and upgrades from older Scala versions.
+ * Developers should not rely on this. + * + * @note The Scala team has decided to enact a special deprecation policy for the 2.12 release:
+ * + * As an upgrade from Scala 2.11 to Scala 2.12 also requires upgrading from Java 6 to Java 8, + * no deprecated elements will be removed in this release to ease migration and upgrades + * from older Scala versions. + * + * @see The official documentation on [[http://www.scala-lang.org/news/2.11.0/#binary-compatibility binary compatibility]]. * @param message the message to print during compilation if the definition is accessed * @param since a string identifying the first version in which the definition was deprecated * @since 2.3 + * @see [[scala.deprecatedInheritance]] + * @see [[scala.deprecatedOverriding]] + * @see [[scala.deprecatedName]] */ @getter @setter @beanGetter @beanSetter class deprecated(message: String = "", since: String = "") extends scala.annotation.StaticAnnotation diff --git a/src/library/scala/deprecatedInheritance.scala b/src/library/scala/deprecatedInheritance.scala index 7614a96f95f6..b85d07b0bdd5 100644 --- a/src/library/scala/deprecatedInheritance.scala +++ b/src/library/scala/deprecatedInheritance.scala @@ -11,12 +11,28 @@ package scala /** An annotation that designates that inheriting from a class is deprecated. * * This is usually done to warn about a non-final class being made final in a future version. - * Sub-classing such a class then generates a warning. No warnings are generated if the - * subclass is in the same compilation unit. + * Sub-classing such a class then generates a warning. + * + * No warnings are generated if the subclass is in the same compilation unit. + * + * {{{ + * @deprecatedInheritance("this class will be made final", "2.12") + * class Foo + * }}} + * + * {{{ + * val foo = new Foo // no deprecation warning + * class Bar extends Foo + * // warning: inheritance from class Foo is deprecated (since 2.12): this class will be made final + * // class Bar extends Foo + * // ^ + * }}} * * @param message the message to print during compilation if the class was sub-classed * @param since a string identifying the first version in which inheritance was deprecated * @since 2.10 + * @see [[scala.deprecated]] * @see [[scala.deprecatedOverriding]] + * @see [[scala.deprecatedName]] */ class deprecatedInheritance(message: String = "", since: String = "") extends scala.annotation.StaticAnnotation diff --git a/src/library/scala/deprecatedName.scala b/src/library/scala/deprecatedName.scala index da8b76efc90f..e2322f03639b 100644 --- a/src/library/scala/deprecatedName.scala +++ b/src/library/scala/deprecatedName.scala @@ -10,23 +10,27 @@ package scala import scala.annotation.meta._ -/** - * An annotation that designates the name of the parameter to which it is - * applied as deprecated. Using that name in a named argument generates - * a deprecation warning. - * - * For instance, evaluating the code below in the Scala interpreter - * {{{ - * def inc(x: Int, @deprecatedName('y) n: Int): Int = x + n - * inc(1, y = 2) - * }}} - * will produce the following output: - * {{{ - * warning: there were 1 deprecation warnings; re-run with -deprecation for details - * res0: Int = 3 - * }}} - * - * @since 2.8.1 - */ + + /** An annotation that designates that the name of a parameter is deprecated. + * + * Using this name in a named argument generates a deprecation warning. + * + * For instance, evaluating the code below in the Scala interpreter (with `-deprecation`) + * {{{ + * def inc(x: Int, @deprecatedName('y, "2.12") n: Int): Int = x + n + * inc(1, y = 2) + * }}} + * will produce the following warning: + * {{{ + * warning: the parameter name y is deprecated (since 2.12): use n instead + * inc(1, y = 2) + * ^ + * }}} + * + * @since 2.8.1 + * @see [[scala.deprecated]] + * @see [[scala.deprecatedInheritance]] + * @see [[scala.deprecatedOverriding]] + */ @param class deprecatedName(name: Symbol = Symbol(""), since: String = "") extends scala.annotation.StaticAnnotation diff --git a/src/library/scala/deprecatedOverriding.scala b/src/library/scala/deprecatedOverriding.scala index 26a9d9ee7d56..ee887db220c6 100644 --- a/src/library/scala/deprecatedOverriding.scala +++ b/src/library/scala/deprecatedOverriding.scala @@ -12,9 +12,28 @@ package scala * * Overriding such a member in a sub-class then generates a warning. * + * {{{ + * class Foo { + * @deprecatedOverriding("this method will be made final", "2.12") + * def add(x: Int, y: Int) = x + y + * } + * }}} + * + * {{{ + * class Bar extends Foo // no deprecation warning + * class Baz extends Foo { + * override def add(x: Int, y: Int) = x - y + * } + * // warning: overriding method add in class Foo is deprecated (since 2.12): this method will be made final + * // override def add(x: Int, y: Int) = x - y + * // ^ + * }}} + * * @param message the message to print during compilation if the member was overridden * @param since a string identifying the first version in which overriding was deprecated * @since 2.10 + * @see [[scala.deprecated]] * @see [[scala.deprecatedInheritance]] + * @see [[scala.deprecatedName]] */ class deprecatedOverriding(message: String = "", since: String = "") extends scala.annotation.StaticAnnotation From a45509cfe9a40b83e92483471889f9a909bea590 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 30 May 2016 08:52:41 +0200 Subject: [PATCH 074/153] Don't pass -opt to starr / locker build in the bootstrap script Renaming -Yopt to -opt revealed that we're passing the flag when building the locker (and optionally the starr) version. This is not necessary: when building the next stage with the flag enabled, the same optimizations are performed no matter if the current stage was built with the flag or not. --- scripts/jobs/integrate/bootstrap | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index 05c7d22b26b4..76673b4f32c5 100644 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -494,7 +494,6 @@ bootstrap() { -Dremote.snapshot.repository=NOPE\ -Dremote.release.repository=$releaseTempRepoUrl\ -Drepository.credentials.id=$releaseTempRepoCred\ - -Dscalac.args.optimise=-opt:l:classpath\ -Ddocs.skip=1\ -Dlocker.skip=1\ $publishStarrPrivateTask >> $baseDir/logs/builds 2>&1 @@ -516,7 +515,6 @@ bootstrap() { $SET_STARR\ -Dremote.release.repository=$releaseTempRepoUrl\ -Drepository.credentials.id=$releaseTempRepoCred\ - -Dscalac.args.optimise=-opt:l:classpath\ -Ddocs.skip=1\ -Dlocker.skip=1\ $publishLockerPrivateTask >> $baseDir/logs/builds 2>&1 From 7b132f39b82e4fc47cd95eadce9e3f22da8c8d82 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 31 May 2016 15:19:49 +1000 Subject: [PATCH 075/153] Avoid tree sharing with substituteThis The underlying transformer has a by-name parameter for the to provide the `to` tree, but this was strict in the layers of API above. Tree sharing is frowned upon in general as it leads to cross talk when, e.g., the erasure typechecker mutates the `tpe` field of the shared tree in different context. --- src/reflect/scala/reflect/api/Internals.scala | 6 +++--- src/reflect/scala/reflect/internal/Internals.scala | 2 +- src/reflect/scala/reflect/internal/Trees.scala | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/reflect/scala/reflect/api/Internals.scala b/src/reflect/scala/reflect/api/Internals.scala index 9b7112f01178..2c8f84be0baa 100644 --- a/src/reflect/scala/reflect/api/Internals.scala +++ b/src/reflect/scala/reflect/api/Internals.scala @@ -116,7 +116,7 @@ trait Internals { self: Universe => /** Substitute given tree `to` for occurrences of nodes that represent * `C.this`, where `C` refers to the given class `clazz`. */ - def substituteThis(tree: Tree, clazz: Symbol, to: Tree): Tree + def substituteThis(tree: Tree, clazz: Symbol, to: => Tree): Tree /** A factory method for `ClassDef` nodes. */ @@ -391,7 +391,7 @@ trait Internals { self: Universe => def substituteTypes(from: List[Symbol], to: List[Type]): Tree = internal.substituteTypes(tree, from, to) /** @see [[internal.substituteThis]] */ - def substituteThis(clazz: Symbol, to: Tree): Tree = internal.substituteThis(tree, clazz, to) + def substituteThis(clazz: Symbol, to: => Tree): Tree = internal.substituteThis(tree, clazz, to) } /** Extension methods for symbols */ @@ -1143,7 +1143,7 @@ trait Internals { self: Universe => /** @see [[InternalApi.substituteThis]] */ @deprecated("use `internal.substituteThis` instead or import `internal.decorators._` for infix syntax", "2.11.0") - def substituteThis(clazz: Symbol, to: Tree): Tree = internal.substituteThis(tree, clazz, to) + def substituteThis(clazz: Symbol, to: => Tree): Tree = internal.substituteThis(tree, clazz, to) } /** Scala 2.10 compatibility enrichments for Tree. */ diff --git a/src/reflect/scala/reflect/internal/Internals.scala b/src/reflect/scala/reflect/internal/Internals.scala index 1a48701ca72b..a07441e3ca21 100644 --- a/src/reflect/scala/reflect/internal/Internals.scala +++ b/src/reflect/scala/reflect/internal/Internals.scala @@ -29,7 +29,7 @@ trait Internals extends api.Internals { def freeTypes(tree: Tree): List[FreeTypeSymbol] = tree.freeTypes def substituteSymbols(tree: Tree, from: List[Symbol], to: List[Symbol]): Tree = tree.substituteSymbols(from, to) def substituteTypes(tree: Tree, from: List[Symbol], to: List[Type]): Tree = tree.substituteTypes(from, to) - def substituteThis(tree: Tree, clazz: Symbol, to: Tree): Tree = tree.substituteThis(clazz, to) + def substituteThis(tree: Tree, clazz: Symbol, to: => Tree): Tree = tree.substituteThis(clazz, to) def attachments(tree: Tree): Attachments { type Pos = Position } = tree.attachments def updateAttachment[T: ClassTag](tree: Tree, attachment: T): tree.type = tree.updateAttachment(attachment) def removeAttachment[T: ClassTag](tree: Tree): tree.type = tree.removeAttachment[T] diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index c9dfd0c337a8..77097d892d43 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -181,7 +181,7 @@ trait Trees extends api.Trees { def substituteTypes(from: List[Symbol], to: List[Type]): Tree = new TreeTypeSubstituter(from, to)(this) - def substituteThis(clazz: Symbol, to: Tree): Tree = + def substituteThis(clazz: Symbol, to: => Tree): Tree = new ThisSubstituter(clazz, to) transform this def hasExistingSymbol = (symbol ne null) && (symbol ne NoSymbol) From 4c2f6f3cb1e0eee11facae8c44e3cd7db11378f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Sat, 28 May 2016 09:23:05 +0200 Subject: [PATCH 076/153] Privatize the deprecated members of `immutable.Range`. The implementation of these obscure members of `Range` are uselessly complicated for the purposes of `Range` itself. Making them private will allow to relax their semantics to the specific needs of `Range`, making them simpler, together with the initialization code of `Range`. `terminalElement` becomes dead code and is removed. --- src/library/scala/collection/immutable/Range.scala | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 0c24d17c1539..ca4f1f47a7db 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -81,8 +81,7 @@ extends scala.collection.AbstractSeq[Int] || (start == end && !isInclusive) ) - @deprecated("this method will be made private, use `length` instead", "2.11.0") - final val numRangeElements: Int = { + private val numRangeElements: Int = { if (step == 0) throw new IllegalArgumentException("step cannot be 0.") else if (isEmpty) 0 else { @@ -92,8 +91,7 @@ extends scala.collection.AbstractSeq[Int] } } - @deprecated("this method will be made private, use `last` instead", "2.11.0") - final val lastElement = + private val lastElement = if (isEmpty) start - step else step match { case 1 => if (isInclusive) end else end-1 @@ -105,9 +103,6 @@ extends scala.collection.AbstractSeq[Int] else end - step } - @deprecated("this method will be made private", "2.11.0") - final val terminalElement = lastElement + step - /** The last element of this range. This method will return the correct value * even if there are too many elements to iterate over. */ From ec1e80422676f02a088034d1658c7cb7f2e6e663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Sat, 28 May 2016 09:44:33 +0200 Subject: [PATCH 077/153] Relax the semantics of `Range.lastElement` for internal use. `lastElement` is only used in code paths where the range is non-empty. It is therefore wasteful to try and give it a sort of sensible value for empty ranges. --- .../scala/collection/immutable/Range.scala | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index ca4f1f47a7db..2e567501155f 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -91,17 +91,16 @@ extends scala.collection.AbstractSeq[Int] } } - private val lastElement = - if (isEmpty) start - step - else step match { - case 1 => if (isInclusive) end else end-1 - case -1 => if (isInclusive) end else end+1 - case _ => - val remainder = (gap % step).toInt - if (remainder != 0) end - remainder - else if (isInclusive) end - else end - step - } + // This field has a sensible value only for non-empty ranges + private val lastElement = step match { + case 1 => if (isInclusive) end else end-1 + case -1 => if (isInclusive) end else end+1 + case _ => + val remainder = (gap % step).toInt + if (remainder != 0) end - remainder + else if (isInclusive) end + else end - step + } /** The last element of this range. This method will return the correct value * even if there are too many elements to iterate over. From 608387529b790c2a0fc87b4cf5b5324d68d02648 Mon Sep 17 00:00:00 2001 From: Mike Pheasant Date: Wed, 1 Jun 2016 08:51:41 +1000 Subject: [PATCH 078/153] SI-9767 document and test behaviour of String->integer/float conversions We delegate `String`'s extension methods `toInt`, `toFloat`, etc to corresponding methods in the Java standard library. These differ in the way they handle whitespace in the original string. This commit documents and tests the current behaviour. --- .../collection/immutable/StringLike.scala | 22 ++++++++----- .../collection/immutable/StringLikeTest.scala | 31 +++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index b468b09a9d1a..155d25d9339f 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -286,31 +286,39 @@ self => def r(groupNames: String*): Regex = new Regex(toString, groupNames: _*) /** - * @throws java.lang.IllegalArgumentException - If the string does not contain a parsable boolean. + * @throws java.lang.IllegalArgumentException If the string does not contain a parsable `Boolean`. */ def toBoolean: Boolean = parseBoolean(toString) /** - * @throws java.lang.NumberFormatException - If the string does not contain a parsable byte. + * Parse as a `Byte` (string must contain only decimal digits and optional leading `-`). + * @throws java.lang.NumberFormatException If the string does not contain a parsable `Byte`. */ def toByte: Byte = java.lang.Byte.parseByte(toString) /** - * @throws java.lang.NumberFormatException - If the string does not contain a parsable short. + * Parse as a `Short` (string must contain only decimal digits and optional leading `-`). + * @throws java.lang.NumberFormatException If the string does not contain a parsable `Short`. */ def toShort: Short = java.lang.Short.parseShort(toString) /** - * @throws java.lang.NumberFormatException - If the string does not contain a parsable int. + * Parse as an `Int` (string must contain only decimal digits and optional leading `-`). + * @throws java.lang.NumberFormatException If the string does not contain a parsable `Int`. */ def toInt: Int = java.lang.Integer.parseInt(toString) /** - * @throws java.lang.NumberFormatException - If the string does not contain a parsable long. + * Parse as a `Long` (string must contain only decimal digits and optional leading `-`). + * @throws java.lang.NumberFormatException If the string does not contain a parsable `Long`. */ def toLong: Long = java.lang.Long.parseLong(toString) /** - * @throws java.lang.NumberFormatException - If the string does not contain a parsable float. + * Parse as a `Float` (surrounding whitespace is removed with a `trim`). + * @throws java.lang.NumberFormatException If the string does not contain a parsable `Float`. + * @throws java.lang.NullPointerException If the string is null. */ def toFloat: Float = java.lang.Float.parseFloat(toString) /** - * @throws java.lang.NumberFormatException - If the string does not contain a parsable double. + * Parse as a `Double` (surrounding whitespace is removed with a `trim`). + * @throws java.lang.NumberFormatException If the string does not contain a parsable `Double`. + * @throws java.lang.NullPointerException If the string is null. */ def toDouble: Double = java.lang.Double.parseDouble(toString) diff --git a/test/junit/scala/collection/immutable/StringLikeTest.scala b/test/junit/scala/collection/immutable/StringLikeTest.scala index 50be638b8908..44bade860ebd 100644 --- a/test/junit/scala/collection/immutable/StringLikeTest.scala +++ b/test/junit/scala/collection/immutable/StringLikeTest.scala @@ -1,5 +1,6 @@ package scala.collection.immutable +import org.junit.Assert._ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -40,4 +41,34 @@ class StringLikeTest { AssertUtil.assertSameElements("--ch--omp--".split("-"), Array("", "", "ch", "", "omp")) // All the cases! AssertUtil.assertSameElements(twopairs.split(high), Array(twopairs)) //don't split on characters that are half a surrogate pair } + + /* Test for SI-9767 */ + @Test + def testNumericConversion: Unit = { + val sOne = " \t\n 1 \n\r\t " + val sOk = "2" + val sNull:String = null + + AssertUtil.assertThrows[java.lang.NumberFormatException](sOne.toInt) + AssertUtil.assertThrows[java.lang.NumberFormatException](sOne.toLong) + AssertUtil.assertThrows[java.lang.NumberFormatException](sOne.toShort) + AssertUtil.assertThrows[java.lang.NumberFormatException](sOne.toByte) + assertTrue("trim toDouble", sOne.toDouble == 1.0d) + assertTrue("trim toFloat", sOne.toFloat == 1.0f) + + assertTrue("no trim toInt", sOk.toInt == 2) + assertTrue("no trim toLong", sOk.toLong == 2L) + assertTrue("no trim toShort", sOk.toShort == 2.toShort) + assertTrue("no trim toByte", sOk.toByte == 2.toByte) + assertTrue("no trim toDouble", sOk.toDouble == 2.0d) + assertTrue("no trim toFloat", sOk.toFloat == 2.0f) + + AssertUtil.assertThrows[java.lang.NumberFormatException](sNull.toInt, {s => s == "null"}) + AssertUtil.assertThrows[java.lang.NumberFormatException](sNull.toLong, {s => s == "null"}) + AssertUtil.assertThrows[java.lang.NumberFormatException](sNull.toShort, {s => s == "null"}) + AssertUtil.assertThrows[java.lang.NumberFormatException](sNull.toByte, {s => s == "null"}) + + AssertUtil.assertThrows[java.lang.NullPointerException](sNull.toDouble) + AssertUtil.assertThrows[java.lang.NullPointerException](sNull.toFloat) + } } From 0533a3df71e9c855ac68e10d060c2c87d16994e0 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 4 May 2016 21:16:41 +1000 Subject: [PATCH 079/153] Lambda impl methods static and more stably named The body of lambdas is compiled into a synthetic method in the enclosing class. Previously, this method was a public virtual method named `fully$qualified$Class$$anonfun$n`. For lambdas that didn't capture a `this` reference, a static method was used. This commit changes two aspects. Firstly, all lambda impl methods are now emitted static. An extra parameter is added to those that require a this reference. This is an improvement as it: - allows, shorter, more readable names for the lambda impl method - avoids pollution of the vtable of the class. Note that javac uses private instance methods, rather than public static methods. If we followed its lead, we would be unable to support important use cases in our inliner Secondly, the name of the enclosing method has been included in the name of the lambda impl method to improve debuggability and to improve serialization compatibility. The serialization improvement comes from the way that fresh names for the impl methods are allocated: adding or removing lambdas in methods not named "foo" won't change the numbering of the `anonfun$foo$n` impl methods from methods named "foo". This is in line with user expectations about anonymous class and lambda serialization stability. Brian Goetz has described this tricky area well in: http://cr.openjdk.java.net/~briangoetz/eg-attachments/lambda-serialization.html This commit doesn't go as far a Javac, we don't use the hash of the lambda type info, param names, etc to map to a lambda impl method name. As such, we are more prone to the type-1 and -2 failures described there. However, our Scala 2.11.8 has similar characteristics, so we aren't going backwards. Special case in the naming: Use "new" rather than "" for constructor enclosed lambdas, as javac does. I have also changed the way that "delambdafy target" methods are identifed. Rather than relying on the naming convention, I have switched to using a symbol attachment. The assumption is that we only need to identify them from within the same compilation unit. This means we can distinguish impl metbods for expanded functions (ones called from an `apply` method of an ahead-of-time expanded anonfun class), from those that truly end up as targets for lambda metafactory. Only the latter are translated to static methods in this patch. --- .../scala/tools/nsc/ast/TreeGen.scala | 50 ++++++++++++++++-- .../backend/jvm/analysis/BackendUtils.scala | 2 +- .../tools/nsc/transform/Delambdafy.scala | 29 ++++++++--- .../tools/nsc/transform/SpecializeTypes.scala | 1 + .../scala/tools/nsc/transform/UnCurry.scala | 19 +++++-- .../tools/nsc/typechecker/Duplicators.scala | 7 ++- .../reflect/internal/StdAttachments.scala | 2 + .../scala/reflect/internal/Symbols.scala | 2 +- .../reflect/runtime/JavaUniverseForce.scala | 1 + test/files/run/delambdafy_t6028.check | 8 +-- test/files/run/delambdafy_t6555.check | 4 +- .../delambdafy_uncurry_byname_method.check | 4 +- .../files/run/delambdafy_uncurry_method.check | 4 +- test/files/run/t9097.scala | 2 +- .../tools/nsc/backend/jvm/IndySammyTest.scala | 2 +- .../backend/jvm/OptimizedBytecodeTest.scala | 14 ++--- .../jvm/opt/ClosureOptimizerTest.scala | 6 +-- .../nsc/backend/jvm/opt/InlinerTest.scala | 52 +++++++++---------- .../backend/jvm/opt/MethodLevelOptsTest.scala | 2 +- .../scala/tools/testing/BytecodeTesting.scala | 10 +++- 20 files changed, 153 insertions(+), 68 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 0786ceb7c246..3dff4a02c962 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -238,7 +238,8 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { * (outside the synchronized block). * * The idiom works only if the condition is using a volatile field. - * @see http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html + * + * @see http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html */ def mkSynchronizedCheck(clazz: Symbol, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree = mkSynchronizedCheck(mkAttributedThis(clazz), cond, syncBody, stats) @@ -274,8 +275,19 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { } // used to create the lifted method that holds a function's body - def mkLiftedFunctionBodyMethod(localTyper: analyzer.Typer)(owner: Symbol, fun: Function) = - mkMethodForFunctionBody(localTyper)(owner, fun, nme.ANON_FUN_NAME)(additionalFlags = ARTIFACT) + def mkLiftedFunctionBodyMethod(localTyper: global.analyzer.Typer)(owner: global.Symbol, fun: global.Function) = { + def nonLocalEnclosingMember(sym: Symbol): Symbol = { + if (sym.isLocalDummy) sym.enclClass.primaryConstructor + else if (sym.isLocalToBlock) nonLocalEnclosingMember(sym.originalOwner) + else sym + } + val ownerName = nonLocalEnclosingMember(fun.symbol.originalOwner).name match { + case nme.CONSTRUCTOR => nme.NEWkw // do as javac does for the suffix, prefer "new" to "$lessinit$greater$1" + case x => x + } + val newName = nme.ANON_FUN_NAME.append(nme.NAME_JOIN_STRING).append(ownerName) + mkMethodForFunctionBody(localTyper)(owner, fun, newName)(additionalFlags = ARTIFACT) + } /** @@ -310,6 +322,38 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { newDefDef(methSym, moveToMethod(useMethodParams(fun.body)))(tpt = TypeTree(resTp)) } + /** + * Create a new `DefDef` based on `orig` with an explicit self parameter. + * + * Details: + * - Must by run after erasure + * - If `maybeClone` is the identity function, this runs "in place" + * and mutates the symbol of `orig`. `orig` should be discarded + * - Symbol owners and returns are substituted, as are parameter symbols + * - Recursive calls are not rewritten. This is correct if we assume + * that we either: + * - are in "in-place" mode, but can guarantee that no recursive calls exists + * - are associating the RHS with a cloned symbol, but intend for the original + * method to remain and for recursive calls to target it. + */ + final def mkStatic(orig: DefDef, maybeClone: Symbol => Symbol): DefDef = { + assert(phase.erasedTypes, phase) + assert(!orig.symbol.hasFlag(SYNCHRONIZED), orig.symbol.defString) + val origSym = orig.symbol + val origParams = orig.symbol.info.params + val newSym = maybeClone(orig.symbol) + newSym.setFlag(STATIC) + // Add an explicit self parameter + val selfParamSym = newSym.newSyntheticValueParam(newSym.owner.typeConstructor, nme.SELF) + newSym.updateInfo(newSym.info match { + case mt @ MethodType(params, res) => copyMethodType(mt, selfParamSym :: params, res) + }) + val selfParam = ValDef(selfParamSym) + val rhs = orig.rhs.substituteThis(newSym.owner, atPos(newSym.pos)(gen.mkAttributedIdent(selfParamSym))) + .substituteSymbols(origParams, newSym.info.params.drop(1)).changeOwner(origSym -> newSym) + treeCopy.DefDef(orig, orig.mods, orig.name, orig.tparams, (selfParam :: orig.vparamss.head) :: Nil, orig.tpt, rhs).setSymbol(newSym) + } + // TODO: the rewrite to AbstractFunction is superfluous once we compile FunctionN to a SAM type (aka functional interface) def functionClassType(fun: Function): Type = if (isFunctionType(fun.tpe)) abstractFunctionType(fun.vparams.map(_.symbol.tpe), fun.body.tpe.deconst) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index f94642389df8..6d3c3f3863c2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -121,7 +121,7 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { def getBoxedUnit: FieldInsnNode = new FieldInsnNode(GETSTATIC, srBoxedUnitRef.internalName, "UNIT", srBoxedUnitRef.descriptor) - private val anonfunAdaptedName = """.*\$anonfun\$\d+\$adapted""".r + private val anonfunAdaptedName = """.*\$anonfun\$.*\$\d+\$adapted""".r def hasAdaptedImplMethod(closureInit: ClosureInstantiation): Boolean = { isBuiltinFunctionType(Type.getReturnType(closureInit.lambdaMetaFactoryCall.indy.desc).getInternalName) && anonfunAdaptedName.pattern.matcher(closureInit.lambdaMetaFactoryCall.implMethod.getName).matches diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index d350ca8e1757..1dfc1330c6a5 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -61,6 +61,9 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre private def mkLambdaMetaFactoryCall(fun: Function, target: Symbol, functionalInterface: Symbol, samUserDefined: Symbol, isSpecialized: Boolean): Tree = { val pos = fun.pos + def isSelfParam(p: Symbol) = p.isSynthetic && p.name == nme.SELF + val hasSelfParam = isSelfParam(target.firstParam) + val allCapturedArgRefs = { // find which variables are free in the lambda because those are captures that need to be // passed into the constructor of the anonymous function class @@ -68,7 +71,8 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre gen.mkAttributedRef(capture) setPos pos ).toList - if (target hasFlag STATIC) captureArgs // no `this` reference needed + if (!hasSelfParam) captureArgs.filterNot(arg => isSelfParam(arg.symbol)) + else if (currentMethod.hasFlag(Flags.STATIC)) captureArgs else (gen.mkAttributedThis(fun.symbol.enclClass) setPos pos) :: captureArgs } @@ -179,7 +183,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val numCaptures = targetParams.length - functionParamTypes.length val (targetCapturedParams, targetFunctionParams) = targetParams.splitAt(numCaptures) - val methSym = oldClass.newMethod(target.name.append("$adapted").toTermName, target.pos, target.flags | FINAL | ARTIFACT) + val methSym = oldClass.newMethod(target.name.append("$adapted").toTermName, target.pos, target.flags | FINAL | ARTIFACT | STATIC) val bridgeCapturedParams = targetCapturedParams.map(param => methSym.newSyntheticValueParam(param.tpe, param.name.toTermName)) val bridgeFunctionParams = map2(targetFunctionParams, bridgeParamTypes)((param, tp) => methSym.newSyntheticValueParam(tp, param.name.toTermName)) @@ -223,10 +227,8 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre private def transformFunction(originalFunction: Function): Tree = { val target = targetMethod(originalFunction) - target.makeNotPrivate(target.owner) - - // must be done before calling createBoxingBridgeMethod and mkLambdaMetaFactoryCall - if (!(target hasFlag STATIC) && !methodReferencesThis(target)) target setFlag STATIC + assert(target.hasFlag(Flags.STATIC)) + target.setFlag(notPRIVATE) val funSym = originalFunction.tpe.typeSymbolDirect // The functional interface that can be used to adapt the lambda target method `target` to the given function type. @@ -252,11 +254,22 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // here's the main entry point of the transform override def transform(tree: Tree): Tree = tree match { // the main thing we care about is lambdas - case fun: Function => super.transform(transformFunction(fun)) + case fun: Function => + super.transform(transformFunction(fun)) case Template(_, _, _) => + def pretransform(tree: Tree): Tree = tree match { + case dd: DefDef if dd.symbol.isDelambdafyTarget => + if (!dd.symbol.hasFlag(STATIC) && methodReferencesThis(dd.symbol)) { + gen.mkStatic(dd, sym => sym) + } else { + dd.symbol.setFlag(STATIC) + dd + } + case t => t + } try { // during this call boxingBridgeMethods will be populated from the Function case - val Template(parents, self, body) = super.transform(tree) + val Template(parents, self, body) = super.transform(deriveTemplate(tree)(_.mapConserve(pretransform))) Template(parents, self, body ++ boxingBridgeMethods) } finally boxingBridgeMethods.clear() case _ => super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index e894c58b1ac9..40ab8c0cf896 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -1329,6 +1329,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { class SpecializationDuplicator(casts: Map[Symbol, Type]) extends Duplicator(casts) { override def retyped(context: Context, tree: Tree, oldThis: Symbol, newThis: Symbol, env: scala.collection.Map[Symbol, Type]): Tree = enteringSpecialize(super.retyped(context, tree, oldThis, newThis, env)) + } /** A tree symbol substituter that substitutes on type skolems. diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index e0b1543f2441..374e8430d819 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -213,6 +213,7 @@ abstract class UnCurry extends InfoTransform // Expand the function body into an anonymous class gen.expandFunction(localTyper)(fun, inConstructorFlag) } else { + val mustExpand = mustExpandFunction(fun) // method definition with the same arguments, return type, and body as the original lambda val liftedMethod = gen.mkLiftedFunctionBodyMethod(localTyper)(fun.symbol.owner, fun) @@ -221,11 +222,18 @@ abstract class UnCurry extends InfoTransform gen.mkForwarder(gen.mkAttributedRef(liftedMethod.symbol), (fun.vparams map (_.symbol)) :: Nil) )) + if (!mustExpand) { + liftedMethod.symbol.updateAttachment(DelambdafyTarget) + liftedMethod.updateAttachment(DelambdafyTarget) + } + val typedNewFun = localTyper.typedPos(fun.pos)(Block(liftedMethod, super.transform(newFun))) - if (mustExpandFunction(fun)) { + if (mustExpand) { val Block(stats, expr : Function) = typedNewFun treeCopy.Block(typedNewFun, stats, gen.expandFunction(localTyper)(expr, inConstructorFlag)) - } else typedNewFun + } else { + typedNewFun + } } def transformArgs(pos: Position, fun: Symbol, args: List[Tree], formals: List[Type]) = { @@ -341,13 +349,18 @@ abstract class UnCurry extends InfoTransform private def isSelfSynchronized(ddef: DefDef) = ddef.rhs match { case Apply(fn @ TypeApply(Select(sel, _), _), _) => - fn.symbol == Object_synchronized && sel.symbol == ddef.symbol.enclClass && !ddef.symbol.enclClass.isTrait + fn.symbol == Object_synchronized && sel.symbol == ddef.symbol.enclClass && !ddef.symbol.enclClass.isTrait && + !ddef.symbol.isDelambdafyTarget /* these become static later, unsuitable for ACC_SYNCHRONIZED */ case _ => false } /** If an eligible method is entirely wrapped in a call to synchronized * locked on the same instance, remove the synchronized scaffolding and * mark the method symbol SYNCHRONIZED for bytecode generation. + * + * Delambdafy targets are deemed ineligible as the Delambdafy phase will + * replace `this.synchronized` with `$this.synchronzed` now that it emits + * all lambda impl methods as static. */ private def translateSynchronized(tree: Tree) = tree match { case dd @ DefDef(_, _, _, _, _, Apply(fn, body :: Nil)) if isSelfSynchronized(dd) => diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 0c10242950ed..78e72cf771e7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -229,7 +229,12 @@ abstract class Duplicators extends Analyzer { case ddef @ DefDef(_, _, _, _, tpt, rhs) => ddef.tpt modifyType fixType - super.typed(ddef.clearType(), mode, pt) + val result = super.typed(ddef.clearType(), mode, pt) + // TODO this is a hack, we really need a cleaner way to transport symbol attachments to duplicated methods + // bodies in specialized subclasses. + if (ddef.hasAttachment[DelambdafyTarget.type]) + result.symbol.updateAttachment(DelambdafyTarget) + result case fun: Function => debuglog("Clearing the type and retyping Function: " + fun) diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index 0243dd48d2d8..ef95b3884317 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -51,6 +51,8 @@ trait StdAttachments { */ case class SAMFunction(samTp: Type, sam: Symbol) extends PlainAttachment + case object DelambdafyTarget extends PlainAttachment + /** When present, indicates that the host `Ident` has been created from a backquoted identifier. */ case object BackquotedIdentifierAttachment extends PlainAttachment diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 49202cd71e2d..3b886d357fde 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -807,7 +807,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME) final def isDelambdafyFunction = isSynthetic && (name containsName tpnme.DELAMBDAFY_LAMBDA_CLASS_NAME) - final def isDelambdafyTarget = isArtifact && isMethod && (name containsName tpnme.ANON_FUN_NAME) + final def isDelambdafyTarget = isArtifact && isMethod && hasAttachment[DelambdafyTarget.type] final def isDefinedInPackage = effectiveOwner.isPackageClass final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index d50debd7ee93..28222cf9a7fd 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -38,6 +38,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.FixedMirrorTypeCreator this.CompoundTypeTreeOriginalAttachment this.SAMFunction + this.DelambdafyTarget this.BackquotedIdentifierAttachment this.ForAttachment this.SyntheticUnitAttachment diff --git a/test/files/run/delambdafy_t6028.check b/test/files/run/delambdafy_t6028.check index b90dea62ed69..8b0ae7e9b97e 100644 --- a/test/files/run/delambdafy_t6028.check +++ b/test/files/run/delambdafy_t6028.check @@ -11,7 +11,7 @@ package { def foo(methodParam: String): Function0 = { val methodLocal: String = ""; { - (() => T.this.$anonfun$1(methodParam, methodLocal)) + (() => T.this.$anonfun$foo$1(methodParam, methodLocal)) } }; def bar(barParam: String): Object = { @@ -21,10 +21,10 @@ package { def tryy(tryyParam: String): Function0 = { var tryyLocal: runtime.ObjectRef = scala.runtime.ObjectRef.create(""); { - (() => T.this.$anonfun$2(tryyParam, tryyLocal)) + (() => T.this.$anonfun$tryy$1(tryyParam, tryyLocal)) } }; - final private[this] def $anonfun$1(methodParam$1: String, methodLocal$1: String): String = T.this.classParam.+(T.this.field()).+(methodParam$1).+(methodLocal$1); + final private[this] def $anonfun$foo$1(methodParam$1: String, methodLocal$1: String): String = T.this.classParam.+(T.this.field()).+(methodParam$1).+(methodLocal$1); abstract trait MethodLocalTrait$1 extends Object { def /*MethodLocalTrait$1*/$init$(barParam$1: String): Unit = { () @@ -54,7 +54,7 @@ package { T.this.MethodLocalObject$lzycompute$1(barParam$1, MethodLocalObject$module$1) else MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type](); - final private[this] def $anonfun$2(tryyParam$1: String, tryyLocal$1: runtime.ObjectRef): Unit = try { + final private[this] def $anonfun$tryy$1(tryyParam$1: String, tryyLocal$1: runtime.ObjectRef): Unit = try { tryyLocal$1.elem = tryyParam$1 } finally () } diff --git a/test/files/run/delambdafy_t6555.check b/test/files/run/delambdafy_t6555.check index b6ccebde78f0..d8b834edc7ce 100644 --- a/test/files/run/delambdafy_t6555.check +++ b/test/files/run/delambdafy_t6555.check @@ -6,8 +6,8 @@ package { () }; private[this] val f: String => String = { - final def $anonfun(param: String): String = param; - ((param: String) => $anonfun(param)) + final def $anonfun$f(param: String): String = param; + ((param: String) => $anonfun$f(param)) }; def f(): String => String = Foo.this.f } diff --git a/test/files/run/delambdafy_uncurry_byname_method.check b/test/files/run/delambdafy_uncurry_byname_method.check index e0f281b1cd8c..71e404ce64f5 100644 --- a/test/files/run/delambdafy_uncurry_byname_method.check +++ b/test/files/run/delambdafy_uncurry_byname_method.check @@ -7,8 +7,8 @@ package { }; def bar(x: () => String): String = x.apply(); def foo(): String = Foo.this.bar({ - final def $anonfun(): String = ""; - (() => $anonfun()) + final def $anonfun$foo(): String = ""; + (() => $anonfun$foo()) }) } } diff --git a/test/files/run/delambdafy_uncurry_method.check b/test/files/run/delambdafy_uncurry_method.check index 5ee3d174b3a0..8aa0b92054b3 100644 --- a/test/files/run/delambdafy_uncurry_method.check +++ b/test/files/run/delambdafy_uncurry_method.check @@ -7,8 +7,8 @@ package { }; def bar(): Unit = { val f: Int => Int = { - final def $anonfun(x: Int): Int = x.+(1); - ((x: Int) => $anonfun(x)) + final def $anonfun|(x: Int): Int = x.+(1); + ((x: Int) => $anonfun|(x)) }; () } diff --git a/test/files/run/t9097.scala b/test/files/run/t9097.scala index 49c0bbe79a19..49c9e2f2e5d8 100644 --- a/test/files/run/t9097.scala +++ b/test/files/run/t9097.scala @@ -28,6 +28,6 @@ object Test extends StoreReporterDirectTest { assert(!storeReporter.hasErrors, message = filteredInfos map (_.msg) mkString "; ") val out = baos.toString("UTF-8") // was 2 before the fix, the two PackageDefs for a would both contain the ClassDef for the closure - assert(out.lines.count(_ contains "def $anonfun$1(x$1: Int): String") == 1, out) + assert(out.lines.count(_ contains "def $anonfun$hihi$1(x$1: Int): String") == 1, out) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala index 2bcbcc870cf5..1ad02c10cf00 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala @@ -43,7 +43,7 @@ class IndySammyTest extends BytecodeTesting { val c = compileClass(s"class C { ${lamDef(from, to, body)}; ${appDef(arg)} }", allowMessage = allowMessage) val applySig = getAsmMethod(funClass, "apply").desc - val anonfun = getMethod(c, "C$$$anonfun$1") + val anonfun = getMethod(c, "$anonfun$lam$1") val lamInsn = getInstructions(c, "lam").dropNonOp val applyInvoke = getMethod(c, "app") diff --git a/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala index 8cf6a655d232..b64a5ae3ceff 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala @@ -43,9 +43,9 @@ class OptimizedBytecodeTest extends BytecodeTesting { val c = compileClass(code) assertSameSummary(getMethod(c, "t"), List( - LDC, ASTORE, ALOAD /*0*/, ALOAD /*1*/, "C$$$anonfun$1", IRETURN)) - assertSameSummary(getMethod(c, "C$$$anonfun$1"), List(LDC, "C$$$anonfun$2", IRETURN)) - assertSameSummary(getMethod(c, "C$$$anonfun$2"), List(-1 /*A*/, GOTO /*A*/)) + LDC, ASTORE, ALOAD /*0*/, ALOAD /*1*/, "$anonfun$t$1", IRETURN)) + assertSameSummary(getMethod(c, "$anonfun$t$1"), List(ALOAD, IFNONNULL, ACONST_NULL, ATHROW, -1, LDC, "$anonfun$t$2", IRETURN)) + assertSameSummary(getMethod(c, "$anonfun$t$2"), List(-1 /*A*/, GOTO /*A*/)) } @Test @@ -295,9 +295,9 @@ class OptimizedBytecodeTest extends BytecodeTesting { |} """.stripMargin val c = compileClass(code, allowMessage = _.msg.contains("exception handler declared in the inlined method")) - assertInvoke(getMethod(c, "f1a"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "f1a"), "C", "$anonfun$f1a$1") assertInvoke(getMethod(c, "f1b"), "C", "wrapper1") - assertInvoke(getMethod(c, "f2a"), "C", "C$$$anonfun$3") + assertInvoke(getMethod(c, "f2a"), "C", "$anonfun$f2a$1") assertInvoke(getMethod(c, "f2b"), "C", "wrapper2") } @@ -331,7 +331,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { |class Listt """.stripMargin val List(c, nil, nilMod, listt) = compileClasses(code) - assertInvoke(getMethod(c, "t"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "t"), "C", "$anonfun$t$1") } @Test @@ -357,6 +357,6 @@ class OptimizedBytecodeTest extends BytecodeTesting { def optimiseEnablesNewOpt(): Unit = { val code = """class C { def t = (1 to 10) foreach println }""" val List(c) = readAsmClasses(newCompiler(extraArgs = "-optimise -deprecation").compileToBytes(code, allowMessage = _.msg.contains("is deprecated"))) - assertInvoke(getMethod(c, "t"), "C", "C$$$anonfun$1") // range-foreach inlined from classpath + assertInvoke(getMethod(c, "t"), "C", "$anonfun$t$1") // range-foreach inlined from classpath } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala index 2da2ecdb723a..f672237f103c 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ClosureOptimizerTest.scala @@ -28,7 +28,7 @@ class ClosureOptimizerTest extends BytecodeTesting { val c = compileClass(code) val t = getAsmMethod(c, "t") - val bodyCall = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Nothing$") + val bodyCall = findInstr(t, "INVOKESTATIC C.$anonfun$t$1 ()Lscala/runtime/Nothing$") assert(bodyCall.getNext.getOpcode == ATHROW) } @@ -44,7 +44,7 @@ class ClosureOptimizerTest extends BytecodeTesting { val c = compileClass(code) val t = getAsmMethod(c, "t") - val bodyCall = findInstr(t, "INVOKESTATIC C.C$$$anonfun$1 ()Lscala/runtime/Null$") + val bodyCall = findInstr(t, "INVOKESTATIC C.$anonfun$t$1 ()Lscala/runtime/Null$") assert(bodyCall.getNext.getOpcode == POP) assert(bodyCall.getNext.getNext.getOpcode == ACONST_NULL) } @@ -62,7 +62,7 @@ class ClosureOptimizerTest extends BytecodeTesting { val c = compileClass(code) assertSameCode(getMethod(c, "t"), List(VarOp(ALOAD, 1), Invoke(INVOKEVIRTUAL, "scala/collection/immutable/List", "head", "()Ljava/lang/Object;", false), - TypeOp(CHECKCAST, "java/lang/String"), Invoke(INVOKESTATIC, "C", "C$$$anonfun$1", "(Ljava/lang/String;)Ljava/lang/String;", false), + TypeOp(CHECKCAST, "java/lang/String"), Invoke(INVOKESTATIC, "C", "$anonfun$t$1", "(Ljava/lang/String;)Ljava/lang/String;", false), Op(ARETURN))) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 333792677aeb..7234659a1d52 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -945,11 +945,11 @@ class InlinerTest extends BytecodeTesting { val t1 = getMethod(c, "t1") assertNoIndy(t1) // the indy call is inlined into t, and the closure elimination rewrites the closure invocation to the body method - assertInvoke(t1, "C", "C$$$anonfun$2") + assertInvoke(t1, "C", "$anonfun$m$2") val t2 = getMethod(c, "t2") assertNoIndy(t2) - assertInvoke(t2, "M$", "M$$$anonfun$1") + assertInvoke(t2, "M$", "$anonfun$m$1") } @Test @@ -1033,7 +1033,7 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - assertInvoke(getMethod(c, "t1"), "C", "C$$$anonfun$1") + assertInvoke(getMethod(c, "t1"), "C", "$anonfun$t1$1") assertInvoke(getMethod(c, "t2"), "C", "a") assertInvoke(getMethod(c, "t3"), "C", "b") assertNoInvoke(getMethod(c, "t4")) @@ -1097,8 +1097,8 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) - assertInvoke(getMethod(c, "t1"), "C", "C$$$anonfun$1") - assertInvoke(getMethod(c, "t2"), "C", "C$$$anonfun$2") + assertInvoke(getMethod(c, "t1"), "C", "$anonfun$t1$1") + assertInvoke(getMethod(c, "t2"), "C", "$anonfun$t2$1") assertInvoke(getMethod(c, "t3"), "scala/Function1", "apply$mcII$sp") assertInvoke(getMethod(c, "t4"), "scala/Function1", "apply$mcII$sp") assertInvoke(getMethod(c, "t5"), "C", "h") @@ -1273,39 +1273,39 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c, _, _) = compile(code) - assertSameSummary(getMethod(c, "t1"), List(BIPUSH, "C$$$anonfun$1", IRETURN)) - assertSameSummary(getMethod(c, "t1a"), List(LCONST_1, "C$$$anonfun$2", IRETURN)) - assertSameSummary(getMethod(c, "t2"), List(ICONST_1, ICONST_2, "C$$$anonfun$3",IRETURN)) + assertSameSummary(getMethod(c, "t1"), List(BIPUSH, "$anonfun$t1$1", IRETURN)) + assertSameSummary(getMethod(c, "t1a"), List(LCONST_1, "$anonfun$t1a$1", IRETURN)) + assertSameSummary(getMethod(c, "t2"), List(ICONST_1, ICONST_2, "$anonfun$t2$1",IRETURN)) // val a = new ValKl(n); new ValKl(anonfun(a.x)).x // value class instantiation-extraction should be optimized by boxing elim assertSameSummary(getMethod(c, "t3"), List( NEW, DUP, ICONST_1, "", ASTORE, NEW, DUP, ALOAD, "x", - "C$$$anonfun$4", + "$anonfun$t3$1", "", "x", IRETURN)) - assertSameSummary(getMethod(c, "t4"), List(BIPUSH, "C$$$anonfun$5", "boxToInteger", ARETURN)) - assertSameSummary(getMethod(c, "t4a"), List(ICONST_1, LDC, "C$$$anonfun$6", LRETURN)) - assertSameSummary(getMethod(c, "t5"), List(BIPUSH, ICONST_3, "C$$$anonfun$7", "boxToInteger", ARETURN)) - assertSameSummary(getMethod(c, "t5a"), List(BIPUSH, BIPUSH, I2B, "C$$$anonfun$8", IRETURN)) - assertSameSummary(getMethod(c, "t6"), List(BIPUSH, "C$$$anonfun$9", RETURN)) - assertSameSummary(getMethod(c, "t7"), List(ICONST_1, "C$$$anonfun$10", RETURN)) - assertSameSummary(getMethod(c, "t8"), List(ICONST_1, LDC, "C$$$anonfun$11", LRETURN)) - assertSameSummary(getMethod(c, "t9"), List(ICONST_1, "boxToInteger", "C$$$anonfun$12", RETURN)) + assertSameSummary(getMethod(c, "t4"), List(BIPUSH, "$anonfun$t4$1", "boxToInteger", ARETURN)) + assertSameSummary(getMethod(c, "t4a"), List(ICONST_1, LDC, "$anonfun$t4a$1", LRETURN)) + assertSameSummary(getMethod(c, "t5"), List(BIPUSH, ICONST_3, "$anonfun$t5$1", "boxToInteger", ARETURN)) + assertSameSummary(getMethod(c, "t5a"), List(BIPUSH, BIPUSH, I2B, "$anonfun$t5a$1", IRETURN)) + assertSameSummary(getMethod(c, "t6"), List(BIPUSH, "$anonfun$t6$1", RETURN)) + assertSameSummary(getMethod(c, "t7"), List(ICONST_1, "$anonfun$t7$1", RETURN)) + assertSameSummary(getMethod(c, "t8"), List(ICONST_1, LDC, "$anonfun$t8$1", LRETURN)) + assertSameSummary(getMethod(c, "t9"), List(ICONST_1, "boxToInteger", "$anonfun$t9$1", RETURN)) // t9a inlines Range.foreach, which is quite a bit of code, so just testing the core - assertInvoke(getMethod(c, "t9a"), "C", "C$$$anonfun$13") + assertInvoke(getMethod(c, "t9a"), "C", "$anonfun$t9a$1") assertInvoke(getMethod(c, "t9a"), "scala/runtime/BoxesRunTime", "boxToInteger") assertSameSummary(getMethod(c, "t10"), List( ICONST_1, ISTORE, ALOAD, ILOAD, - "C$$$anonfun$14", RETURN)) + "$anonfun$t10$1", RETURN)) // t10a inlines Range.foreach - assertInvoke(getMethod(c, "t10a"), "C", "C$$$anonfun$15") + assertInvoke(getMethod(c, "t10a"), "C", "$anonfun$t10a$1") assertDoesNotInvoke(getMethod(c, "t10a"), "boxToInteger") } @@ -1330,8 +1330,8 @@ class InlinerTest extends BytecodeTesting { """.stripMargin val List(c) = compile(code) assertSameCode(getMethod(c, "t1"), List(Op(ICONST_0), Op(ICONST_1), Op(IADD), Op(IRETURN))) - assertEquals(getInstructions(c, "t2") collect { case i: Invoke => i.owner +"."+ i.name }, List( - "scala/runtime/IntRef.create", "C.C$$$anonfun$1")) + assertEquals(getMethod(c, "t2").instructions collect { case i: Invoke => i.owner +"."+ i.name }, List( + "scala/runtime/IntRef.create", "C.$anonfun$t2$1")) } @Test @@ -1449,9 +1449,9 @@ class InlinerTest extends BytecodeTesting { // box-unbox will clean it up assertSameSummary(getMethod(c, "t"), List( - ALOAD, "C$$$anonfun$1", IFEQ /*A*/, - "C$$$anonfun$2", IRETURN, - -1 /*A*/, "C$$$anonfun$3", IRETURN)) + ALOAD, "$anonfun$t$1", IFEQ /*A*/, + "$anonfun$t$2", IRETURN, + -1 /*A*/, "$anonfun$t$3", IRETURN)) } @Test @@ -1501,7 +1501,7 @@ class InlinerTest extends BytecodeTesting { val List(c) = compile(code) val t = getMethod(c, "t") assertNoIndy(t) - assertInvoke(t, "C", "C$$$anonfun$1") + assertInvoke(t, "C", "$anonfun$t$1") } @Test diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 9675e2e4456f..938bc7b84686 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -221,7 +221,7 @@ class MethodLevelOptsTest extends BytecodeTesting { VarOp(ILOAD, 1), VarOp(ILOAD, 2), VarOp(ILOAD, 3), - Invoke(INVOKESTATIC, "C", "C$$$anonfun$1", "(III)I", false), Op(IRETURN))) + Invoke(INVOKESTATIC, "C", "$anonfun$t$1", "(III)I", false), Op(IRETURN))) } @Test diff --git a/test/junit/scala/tools/testing/BytecodeTesting.scala b/test/junit/scala/tools/testing/BytecodeTesting.scala index b11ad271483d..1a0c1e210a48 100644 --- a/test/junit/scala/tools/testing/BytecodeTesting.scala +++ b/test/junit/scala/tools/testing/BytecodeTesting.scala @@ -1,5 +1,6 @@ package scala.tools.testing +import junit.framework.AssertionFailedError import org.junit.Assert._ import scala.collection.JavaConverters._ @@ -245,8 +246,13 @@ object BytecodeTesting { getAsmMethods(c, _ == name) def getAsmMethod(c: ClassNode, name: String): MethodNode = { - val List(m) = getAsmMethods(c, name) - m + val methods = getAsmMethods(c, name) + methods match { + case List(m) => m + case ms => + val allNames = getAsmMethods(c, _ => true).map(_.name) + throw new AssertionFailedError(s"Could not find method named $name among ${allNames}") + } } def getMethods(c: ClassNode, name: String): List[Method] = From f01d061caaae26b3fdff0e4db800292e9b3252c2 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 13 May 2016 13:43:13 +0200 Subject: [PATCH 080/153] Treat self parameter as non-null in the optimizer --- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 2 +- .../backend/jvm/analysis/NullnessAnalyzer.scala | 16 +++++++++++----- .../tools/nsc/backend/jvm/opt/CallGraph.scala | 2 +- .../tools/nsc/backend/jvm/opt/LocalOpt.scala | 2 +- .../nsc/backend/jvm/OptimizedBytecodeTest.scala | 2 +- .../jvm/analysis/NullnessAnalyzerTest.scala | 2 +- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 3dff4a02c962..80a707461c36 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -344,7 +344,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { val newSym = maybeClone(orig.symbol) newSym.setFlag(STATIC) // Add an explicit self parameter - val selfParamSym = newSym.newSyntheticValueParam(newSym.owner.typeConstructor, nme.SELF) + val selfParamSym = newSym.newSyntheticValueParam(newSym.owner.typeConstructor, nme.SELF).setFlag(ARTIFACT) newSym.updateInfo(newSym.info match { case mt @ MethodType(params, res) => copyMethodType(mt, selfParamSym :: params, res) }) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala index 30e73f8ac24f..01afd0d2ef70 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzer.scala @@ -5,8 +5,8 @@ package analysis import java.util import scala.annotation.switch -import scala.tools.asm.{Type, Opcodes} -import scala.tools.asm.tree.{MethodInsnNode, LdcInsnNode, AbstractInsnNode} +import scala.tools.asm.{Opcodes, Type} +import scala.tools.asm.tree.{AbstractInsnNode, LdcInsnNode, MethodInsnNode, MethodNode} import scala.tools.asm.tree.analysis._ import scala.tools.nsc.backend.jvm.opt.BytecodeUtils import BytecodeUtils._ @@ -63,7 +63,7 @@ object NullnessValue { def unknown(insn: AbstractInsnNode) = if (BytecodeUtils.instructionResultSize(insn) == 2) UnknownValue2 else UnknownValue1 } -final class NullnessInterpreter(bTypes: BTypes) extends Interpreter[NullnessValue](Opcodes.ASM5) { +final class NullnessInterpreter(bTypes: BTypes, method: MethodNode) extends Interpreter[NullnessValue](Opcodes.ASM5) { def newValue(tp: Type): NullnessValue = { // ASM loves giving semantics to null. The behavior here is the same as in SourceInterpreter, // which is provided by the framework. @@ -80,7 +80,13 @@ final class NullnessInterpreter(bTypes: BTypes) extends Interpreter[NullnessValu override def newParameterValue(isInstanceMethod: Boolean, local: Int, tp: Type): NullnessValue = { // For instance methods, the `this` parameter is known to be not null. - if (isInstanceMethod && local == 0) NotNullValue + val isThis = local == 0 && (isInstanceMethod || { + method.parameters != null && !method.parameters.isEmpty && { + val p = method.parameters.get(0) + (p.access & Opcodes.ACC_SYNTHETIC) != 0 && p.name == "$this" + } + }) + if (isThis) NotNullValue else super.newParameterValue(isInstanceMethod, local, tp) } @@ -197,7 +203,7 @@ class NullnessFrame(nLocals: Int, nStack: Int) extends AliasingFrame[NullnessVal * This class is required to override the `newFrame` methods, which makes makes sure the analyzer * uses NullnessFrames. */ -class NullnessAnalyzer(bTypes: BTypes) extends Analyzer[NullnessValue](new NullnessInterpreter(bTypes)) { +class NullnessAnalyzer(bTypes: BTypes, method: MethodNode) extends Analyzer[NullnessValue](new NullnessInterpreter(bTypes, method)) { override def newFrame(nLocals: Int, nStack: Int): NullnessFrame = new NullnessFrame(nLocals, nStack) override def newFrame(src: Frame[_ <: NullnessValue]): NullnessFrame = new NullnessFrame(src) } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index e8d1bf203a42..d4ff6493a379 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -103,7 +103,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { val analyzer = { if (compilerSettings.optNullnessTracking && AsmAnalyzer.sizeOKForNullness(methodNode)) { - Some(new AsmAnalyzer(methodNode, definingClass.internalName, new NullnessAnalyzer(btypes))) + Some(new AsmAnalyzer(methodNode, definingClass.internalName, new NullnessAnalyzer(btypes, methodNode))) } else if (AsmAnalyzer.sizeOKForBasicValue(methodNode)) { Some(new AsmAnalyzer(methodNode, definingClass.internalName)) } else None diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala index 5ca0ad2773ae..447ee209b593 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala @@ -397,7 +397,7 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { */ def nullnessOptimizations(method: MethodNode, ownerClassName: InternalName): Boolean = { AsmAnalyzer.sizeOKForNullness(method) && { - lazy val nullnessAnalyzer = new AsmAnalyzer(method, ownerClassName, new NullnessAnalyzer(btypes)) + lazy val nullnessAnalyzer = new AsmAnalyzer(method, ownerClassName, new NullnessAnalyzer(btypes, method)) // When running nullness optimizations the method may still have unreachable code. Analyzer // frames of unreachable instructions are `null`. diff --git a/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala index b64a5ae3ceff..9a0899ffc5f7 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/OptimizedBytecodeTest.scala @@ -44,7 +44,7 @@ class OptimizedBytecodeTest extends BytecodeTesting { assertSameSummary(getMethod(c, "t"), List( LDC, ASTORE, ALOAD /*0*/, ALOAD /*1*/, "$anonfun$t$1", IRETURN)) - assertSameSummary(getMethod(c, "$anonfun$t$1"), List(ALOAD, IFNONNULL, ACONST_NULL, ATHROW, -1, LDC, "$anonfun$t$2", IRETURN)) + assertSameSummary(getMethod(c, "$anonfun$t$1"), List(LDC, "$anonfun$t$2", IRETURN)) assertSameSummary(getMethod(c, "$anonfun$t$2"), List(-1 /*A*/, GOTO /*A*/)) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala index 1de5aa28ca3d..c173bacd4616 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala @@ -21,7 +21,7 @@ class NullnessAnalyzerTest extends BytecodeTesting { import compiler._ import global.genBCode.bTypes.backendUtils._ - def newNullnessAnalyzer(methodNode: MethodNode, classInternalName: InternalName = "C") = new AsmAnalyzer(methodNode, classInternalName, new NullnessAnalyzer(global.genBCode.bTypes)) + def newNullnessAnalyzer(methodNode: MethodNode, classInternalName: InternalName = "C") = new AsmAnalyzer(methodNode, classInternalName, new NullnessAnalyzer(global.genBCode.bTypes, methodNode)) def testNullness(analyzer: AsmAnalyzer[NullnessValue], method: MethodNode, query: String, index: Int, nullness: NullnessValue): Unit = { for (i <- findInstrs(method, query)) { From e077c24525bf8f9bd8b73684e630eb7fc6bcb5f6 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 14 Apr 2016 14:00:33 +1000 Subject: [PATCH 081/153] SI-9390 Emit local defs that don't capture this as static This avoids unnecessary memory retention, and allows lambdas that call the local methods to be serializable, regardless of whether or not the enclosing class is serializable. The second point is especially pressing, given that the enclosing class for local methods defined in a used to be the (serializable) anonymous function class, but as of Scala 2.12 will be the enclosing class of the lambda. This change is similar in spirit to SI-9408 / 93bee55e. --- .../tools/nsc/transform/Delambdafy.scala | 35 +++++++--- test/files/run/t5652.check | 6 +- test/files/run/t5652b.check | 4 +- test/files/run/t5652c.check | 4 +- test/files/run/t9390.scala | 67 +++++++++++++++++++ test/files/run/t9390b.scala | 31 +++++++++ .../backend/jvm/opt/InlineWarningTest.scala | 4 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 2 +- 8 files changed, 135 insertions(+), 18 deletions(-) create mode 100644 test/files/run/t9390.scala create mode 100644 test/files/run/t9390b.scala diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 1dfc1330c6a5..a8933a9ee6b9 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -225,6 +225,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre } } + private def transformFunction(originalFunction: Function): Tree = { val target = targetMethod(originalFunction) assert(target.hasFlag(Flags.STATIC)) @@ -272,6 +273,12 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val Template(parents, self, body) = super.transform(deriveTemplate(tree)(_.mapConserve(pretransform))) Template(parents, self, body ++ boxingBridgeMethods) } finally boxingBridgeMethods.clear() + case dd: DefDef if dd.symbol.isLiftedMethod && !dd.symbol.isDelambdafyTarget => + // SI-9390 emit lifted methods that don't require a `this` reference as STATIC + // delambdafy targets are excluded as they are made static by `transformFunction`. + if (!dd.symbol.hasFlag(STATIC) && !methodReferencesThis(dd.symbol)) + dd.symbol.setFlag(STATIC) + super.transform(tree) case _ => super.transform(tree) } } // DelambdafyTransformer @@ -326,19 +333,28 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // recursively find methods that refer to 'this' directly or indirectly via references to other methods // for each method found add it to the referrers set - private def refersToThis(symbol: Symbol): Boolean = - (thisReferringMethods contains symbol) || - (liftedMethodReferences(symbol) exists refersToThis) && { - // add it early to memoize - debuglog(s"$symbol indirectly refers to 'this'") - thisReferringMethods += symbol - true + private def refersToThis(symbol: Symbol): Boolean = { + var seen = mutable.Set[Symbol]() + def loop(symbol: Symbol): Boolean = { + if (seen(symbol)) false + else { + seen += symbol + (thisReferringMethods contains symbol) || + (liftedMethodReferences(symbol) exists loop) && { + // add it early to memoize + debuglog(s"$symbol indirectly refers to 'this'") + thisReferringMethods += symbol + true + } } + } + loop(symbol) + } private var currentMethod: Symbol = NoSymbol override def traverse(tree: Tree) = tree match { - case DefDef(_, _, _, _, _, _) if tree.symbol.isDelambdafyTarget => + case DefDef(_, _, _, _, _, _) if tree.symbol.isDelambdafyTarget || tree.symbol.isLiftedMethod => // we don't expect defs within defs. At this phase trees should be very flat if (currentMethod.exists) devWarning("Found a def within a def at a phase where defs are expected to be flattened out.") currentMethod = tree.symbol @@ -349,6 +365,9 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // They'll be of the form {(args...) => this.anonfun(args...)} // but we do need to make note of the lifted body method in case it refers to 'this' if (currentMethod.exists) liftedMethodReferences(currentMethod) += targetMethod(fun) + case Apply(sel @ Select(This(_), _), args) if sel.symbol.isLiftedMethod => + if (currentMethod.exists) liftedMethodReferences(currentMethod) += sel.symbol + super.traverseTrees(args) case This(_) => if (currentMethod.exists && tree.symbol == currentMethod.enclClass) { debuglog(s"$currentMethod directly refers to 'this'") diff --git a/test/files/run/t5652.check b/test/files/run/t5652.check index a0fb6fe9b4e5..7c65ba66981d 100644 --- a/test/files/run/t5652.check +++ b/test/files/run/t5652.check @@ -1,7 +1,7 @@ -public default int T1.T1$$g$1() public default int T1.f0() public default void T1.$init$() -public final int A1.A1$$g$2() +public static int T1.T1$$g$1() public int A1.f1() -public final int A2.A2$$g$1() +public static final int A1.A1$$g$2() public int A2.f2() +public static final int A2.A2$$g$1() diff --git a/test/files/run/t5652b.check b/test/files/run/t5652b.check index ca9d0a74f094..0f4290796f2d 100644 --- a/test/files/run/t5652b.check +++ b/test/files/run/t5652b.check @@ -1,4 +1,4 @@ -private final int A1.g$1() +private static final int A1.g$1() public int A1.f1() -private final int A2.g$1() +private static final int A2.g$1() public int A2.f2() diff --git a/test/files/run/t5652c.check b/test/files/run/t5652c.check index 3b889e066dab..5a6d535f0293 100644 --- a/test/files/run/t5652c.check +++ b/test/files/run/t5652c.check @@ -1,6 +1,6 @@ -public final int A1.A1$$g$1() -public final int A1.A1$$g$2() public int A1.f1() public int A1.f2() +public static final int A1.A1$$g$1() +public static final int A1.A1$$g$2() 1 2 diff --git a/test/files/run/t9390.scala b/test/files/run/t9390.scala new file mode 100644 index 000000000000..8d7e1be5572c --- /dev/null +++ b/test/files/run/t9390.scala @@ -0,0 +1,67 @@ +class C { + def methodLift1 = { + def isEven(c: Int) = c % 2 == 0 + val f: Int => Boolean = isEven + f + } + def methodLift2 = { + def isEven(c: Int) = c % 2 == 0 + def isEven0(c: Int) = isEven(c) + val f: Int => Boolean = isEven0 + f + } + + def methodLift3 = { + def isEven(c: Int) = {toString; c % 2 == 0} + def isEven0(c: Int) = isEven(c) + val f: Int => Boolean = isEven0 + f + } +} + +object Test { + def main(args: Array[String]): Unit = { + val c = new C + + { + val f = c.methodLift1 + assert(f(0)) + assert(!f(1)) + val f1 = serializeDeserialize(f) + assert(f1(0)) + assert(!f1(1)) + } + + + { + val f = c.methodLift2 + assert(f(0)) + assert(!f(1)) + val f1 = serializeDeserialize(f) + assert(f1(0)) + assert(!f1(1)) + } + + { + val f = c.methodLift3 + assert(f(0)) + assert(!f(1)) + try { + serializeDeserialize(this) + assert(false) + } catch { + case _: java.io.NotSerializableException => + // expected, the closure in methodLift3 must capture C which is not serializable + } + } + } + + def serializeDeserialize[T <: AnyRef](obj: T): T = { + import java.io._ + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } +} diff --git a/test/files/run/t9390b.scala b/test/files/run/t9390b.scala new file mode 100644 index 000000000000..439e21e0a036 --- /dev/null +++ b/test/files/run/t9390b.scala @@ -0,0 +1,31 @@ +class C { // C is not serializable + def foo = (x: Int) => (y: Int) => x + y + def bar = (x: Int) => (y: Int) => {toString; x + y} +} + +object Test { + def main(args: Array[String]): Unit = { + val c = new C + val f = c.foo + assert(f(1)(2) == 3) + val f1 = serializeDeserialize(f) + assert(f1(1)(2) == 3) + + try { + serializeDeserialize(c.bar) + assert(false) + } catch { + case _: java.io.NotSerializableException => + // expected, lambda transitively refers to this + } + } + + def serializeDeserialize[T <: AnyRef](obj: T): T = { + import java.io._ + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } +} diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index 6161dc7b7324..024cf0c416df 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -113,7 +113,7 @@ class InlineWarningTest extends BytecodeTesting { val warn = """M::f()I is annotated @inline but could not be inlined: - |The callee M::f()I contains the instruction INVOKESPECIAL M.nested$1 ()I + |The callee M::f()I contains the instruction INVOKESTATIC M.nested$1 ()I |that would cause an IllegalAccessError when inlined into class N""".stripMargin var c = 0 @@ -140,7 +140,7 @@ class InlineWarningTest extends BytecodeTesting { val warn = """M::f(Lscala/Function1;)I could not be inlined: - |The callee M::f(Lscala/Function1;)I contains the instruction INVOKESPECIAL M.nested$1 ()I + |The callee M::f(Lscala/Function1;)I contains the instruction INVOKESTATIC M.nested$1 ()I |that would cause an IllegalAccessError when inlined into class N""".stripMargin var c = 0 diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 7234659a1d52..02cd632af176 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -1141,7 +1141,7 @@ class InlinerTest extends BytecodeTesting { val warn = """C::h()I is annotated @inline but could not be inlined: - |The callee C::h()I contains the instruction INVOKESPECIAL C.f$1 ()I + |The callee C::h()I contains the instruction INVOKESTATIC C.f$1 ()I |that would cause an IllegalAccessError when inlined into class D.""".stripMargin val List(c, d) = compile(code, allowMessage = _.msg contains warn) From def22ff08692ba55e607b8948e6159bdda3f48e5 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 27 May 2016 11:12:48 -0700 Subject: [PATCH 082/153] opt: fuse some operations on `Scope`s `Scope`'s `filter` is implemented using `toList`, so may as well start with `toList`ourselves. Also fused some `filter`/`foreach` combos. --- .../nsc/transform/ExtensionMethods.scala | 3 +- .../scala/tools/nsc/typechecker/Namers.scala | 2 +- .../tools/nsc/typechecker/RefChecks.scala | 4 +- .../scala/tools/nsc/typechecker/Typers.scala | 37 ++++++++++--------- .../scala/reflect/internal/Definitions.scala | 7 ++-- .../scala/reflect/internal/Symbols.scala | 6 +-- 6 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 9d02228ab543..f2237a07160d 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -192,8 +192,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { extensionDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] currentOwner.primaryConstructor.makeNotPrivate(NoSymbol) // SI-7859 make param accessors accessible so the erasure can generate unbox operations. - val paramAccessors = currentOwner.info.decls.filter(sym => sym.isParamAccessor && sym.isMethod) - paramAccessors.foreach(_.makeNotPrivate(currentOwner)) + currentOwner.info.decls.foreach(sym => if (sym.isParamAccessor && sym.isMethod) sym.makeNotPrivate(currentOwner)) super.transform(tree) } else if (currentOwner.isStaticOwner) { super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 8943ec810d7e..2773ee19cff1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -463,7 +463,7 @@ trait Namers extends MethodSynthesis { // opening up the package object on the classpath at all if one exists in source. if (m.isPackageObject) { val packageScope = m.enclosingPackageClass.rawInfo.decls - packageScope.filter(_.owner != m.enclosingPackageClass).toList.foreach(packageScope unlink _) + packageScope.foreach(mem => if (mem.owner != m.enclosingPackageClass) packageScope unlink mem) } updatePosFlags(m, tree.pos, moduleFlags) setPrivateWithin(tree, m) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 2d454c2fe6cd..a5a680d13523 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -172,12 +172,12 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // This has become noisy with implicit classes. if (settings.warnPolyImplicitOverload && settings.developer) { - clazz.info.decls filter (x => x.isImplicit && x.typeParams.nonEmpty) foreach { sym => + clazz.info.decls.foreach(sym => if (sym.isImplicit && sym.typeParams.nonEmpty) { // implicit classes leave both a module symbol and a method symbol as residue val alts = clazz.info.decl(sym.name).alternatives filterNot (_.isModule) if (alts.size > 1) alts foreach (x => reporter.warning(x.pos, "parameterized overloaded implicit methods are not visible as view bounds")) - } + }) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index dcf14612c9c8..0b55a732d8e4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2391,19 +2391,20 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } // The block is an anonymous class definitions/instantiation pair // -> members that are hidden by the type of the block are made private - val toHide = ( - classDecls filter (member => - member.isTerm - && member.isPossibleInRefinement - && member.isPublic - && !matchesVisibleMember(member) - ) map (member => member - resetFlag (PROTECTED | LOCAL) - setFlag (PRIVATE | SYNTHETIC_PRIVATE) - setPrivateWithin NoSymbol - ) - ) - syntheticPrivates ++= toHide + classDecls foreach { toHide => + if (toHide.isTerm + && toHide.isPossibleInRefinement + && toHide.isPublic + && !matchesVisibleMember(toHide)) { + (toHide + resetFlag (PROTECTED | LOCAL) + setFlag (PRIVATE | SYNTHETIC_PRIVATE) + setPrivateWithin NoSymbol) + + syntheticPrivates += toHide + } + } + case _ => } } @@ -3641,10 +3642,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper reportAnnotationError(MultipleArgumentListForAnnotationError(ann)) } else { - val annScope = annType.decls - .filter(sym => sym.isMethod && !sym.isConstructor && sym.isJavaDefined) + val annScopeJava = + if (isJava) annType.decls.filter(sym => sym.isMethod && !sym.isConstructor && sym.isJavaDefined) + else EmptyScope // annScopeJava is only used if isJava + val names = mutable.Set[Symbol]() - names ++= (if (isJava) annScope.iterator + names ++= (if (isJava) annScopeJava.iterator else typedFun.tpe.params.iterator) def hasValue = names exists (_.name == nme.value) @@ -3655,7 +3658,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val nvPairs = args map { case arg @ AssignOrNamedArg(Ident(name), rhs) => - val sym = if (isJava) annScope.lookup(name) + val sym = if (isJava) annScopeJava.lookup(name) else findSymbol(typedFun.tpe.params)(_.name == name) if (sym == NoSymbol) { reportAnnotationError(UnknownAnnotationNameError(arg, name)) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index ca6c893d130d..fe6d88e7c749 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -863,12 +863,13 @@ trait Definitions extends api.StandardDefinitions { // Scopes() // must filter out "universal" members (getClass is deferred for some reason) val deferredMembers = ( - tp membersBasedOnFlags (excludedFlags = BridgeAndPrivateFlags, requiredFlags = METHOD) - filter (mem => mem.isDeferredNotJavaDefault && !isUniversalMember(mem)) // TODO: test + tp.membersBasedOnFlags(excludedFlags = BridgeAndPrivateFlags, requiredFlags = METHOD).toList.filter( + mem => mem.isDeferredNotJavaDefault && !isUniversalMember(mem) + ) // TODO: test ) // if there is only one, it's monomorphic and has a single argument list - if (deferredMembers.size == 1 && + if (deferredMembers.lengthCompare(1) == 0 && deferredMembers.head.typeParams.isEmpty && deferredMembers.head.info.paramSectionCount == 1) deferredMembers.head diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 49202cd71e2d..97b7f239f03a 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2036,11 +2036,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } } - private final def caseFieldAccessorsUnsorted: List[Symbol] = - (info.decls filter (_.isCaseAccessorMethod)).toList + private final def caseFieldAccessorsUnsorted: List[Symbol] = info.decls.toList.filter(_.isCaseAccessorMethod) - final def constrParamAccessors: List[Symbol] = - info.decls.filter(sym => !sym.isMethod && sym.isParamAccessor).toList + final def constrParamAccessors: List[Symbol] = info.decls.toList.filter(sym => !sym.isMethod && sym.isParamAccessor) /** The symbol accessed by this accessor (getter or setter) function. */ final def accessed: Symbol = { From 6cd356a9ffc2054f2a3d729a47ceae13c7575e09 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Mon, 30 May 2016 22:45:51 -0700 Subject: [PATCH 083/153] Compute constrParamAccessors once. It's expensive --- .../scala/tools/nsc/typechecker/Typers.scala | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 0b55a732d8e4..72da4498c761 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2068,35 +2068,39 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper case _ => (call, Nil) } - val (superConstr, superArgs) = decompose(rhs) - assert(superConstr.symbol ne null, superConstr)//debug - def superClazz = superConstr.symbol.owner - def superParamAccessors = superClazz.constrParamAccessors // associate superclass paramaccessors with their aliases - if (superConstr.symbol.isPrimaryConstructor && !superClazz.isJavaDefined && sameLength(superParamAccessors, superArgs)) { - for ((superAcc, superArg @ Ident(name)) <- superParamAccessors zip superArgs) { - if (mexists(vparamss)(_.symbol == superArg.symbol)) { - val alias = ( - superAcc.initialize.alias - orElse (superAcc getterIn superAcc.owner) - filter (alias => superClazz.info.nonPrivateMember(alias.name) == alias) - ) - if (alias.exists && !alias.accessed.isVariable && !isRepeatedParamType(alias.accessed.info)) { - val ownAcc = clazz.info decl name suchThat (_.isParamAccessor) match { - case acc if !acc.isDeferred && acc.hasAccessorFlag => acc.accessed - case acc => acc - } - ownAcc match { - case acc: TermSymbol if !acc.isVariable && !isByNameParamType(acc.info) => - debuglog(s"$acc has alias ${alias.fullLocationString}") - acc setAlias alias - case _ => + val (superConstr, superArgs) = decompose(rhs) + if (superConstr.symbol.isPrimaryConstructor) { + val superClazz = superConstr.symbol.owner + if (!superClazz.isJavaDefined) { + val superParamAccessors = superClazz.constrParamAccessors + if (sameLength(superParamAccessors, superArgs)) { + for ((superAcc, superArg@Ident(name)) <- superParamAccessors zip superArgs) { + if (mexists(vparamss)(_.symbol == superArg.symbol)) { + val alias = ( + superAcc.initialize.alias + orElse (superAcc getterIn superAcc.owner) + filter (alias => superClazz.info.nonPrivateMember(alias.name) == alias) + ) + if (alias.exists && !alias.accessed.isVariable && !isRepeatedParamType(alias.accessed.info)) { + val ownAcc = clazz.info decl name suchThat (_.isParamAccessor) match { + case acc if !acc.isDeferred && acc.hasAccessorFlag => acc.accessed + case acc => acc + } + ownAcc match { + case acc: TermSymbol if !acc.isVariable && !isByNameParamType(acc.info) => + debuglog(s"$acc has alias ${alias.fullLocationString}") + acc setAlias alias + case _ => + } + } } } } } } + pending.foreach(ErrorUtils.issueTypeError) } From 3f685073923d76de08ffdba78075f2267ee56133 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 2 Jun 2016 11:18:02 +1000 Subject: [PATCH 084/153] Drop local suffix in lambda impl method name --- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 80a707461c36..14ee7d7a7897 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -283,7 +283,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { } val ownerName = nonLocalEnclosingMember(fun.symbol.originalOwner).name match { case nme.CONSTRUCTOR => nme.NEWkw // do as javac does for the suffix, prefer "new" to "$lessinit$greater$1" - case x => x + case x => x.dropLocal } val newName = nme.ANON_FUN_NAME.append(nme.NAME_JOIN_STRING).append(ownerName) mkMethodForFunctionBody(localTyper)(owner, fun, newName)(additionalFlags = ARTIFACT) From 7952cd1651b6ed1fe0cd68198e49cf90423242d8 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 1 Jun 2016 23:25:35 +0200 Subject: [PATCH 085/153] Fix comparisons involving NaN Floating point comparisons involving NaN should always return false, except for !=. Fixes a regression introduced by #4963. --- .../tools/nsc/backend/ScalaPrimitives.scala | 4 +- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 26 ++++++------- .../tools/nsc/backend/jvm/BCodeHelpers.scala | 1 + .../junit/scala/lang/primitives/NaNTest.scala | 38 +++++++++++++++++++ 4 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 test/junit/scala/lang/primitives/NaNTest.scala diff --git a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala index 00771b6b8c2b..dfd5b07a3b30 100644 --- a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala +++ b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala @@ -61,8 +61,8 @@ abstract class ScalaPrimitives { final val NE = 43 // x != y final val LT = 44 // x < y final val LE = 45 // x <= y - final val GE = 46 // x > y - final val GT = 47 // x >= y + final val GT = 46 // x > y + final val GE = 47 // x >= y // Boolean unary operations final val ZNOT = 50 // !x diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 5d152ef0e8e2..d7106ae908ff 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -1110,22 +1110,19 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { } /* Emit code to compare the two top-most stack values using the 'op' operator. */ - private def genCJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label) { - if (targetIfNoJump == success) genCJUMP(failure, success, op.negate, tk, targetIfNoJump) + private def genCJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label, negated: Boolean = false) { + if (targetIfNoJump == success) genCJUMP(failure, success, op.negate, tk, targetIfNoJump, negated = !negated) else { if (tk.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT bc.emitIF_ICMP(op, success) } else if (tk.isRef) { // REFERENCE(_) | ARRAY(_) bc.emitIF_ACMP(op, success) } else { + def useCmpG = if (negated) op == TestOp.GT || op == TestOp.GE else op == TestOp.LT || op == TestOp.LE (tk: @unchecked) match { case LONG => emit(asm.Opcodes.LCMP) - case FLOAT => - if (op == TestOp.LT || op == TestOp.LE) emit(asm.Opcodes.FCMPG) - else emit(asm.Opcodes.FCMPL) - case DOUBLE => - if (op == TestOp.LT || op == TestOp.LE) emit(asm.Opcodes.DCMPG) - else emit(asm.Opcodes.DCMPL) + case FLOAT => emit(if (useCmpG) asm.Opcodes.FCMPG else asm.Opcodes.FCMPL) + case DOUBLE => emit(if (useCmpG) asm.Opcodes.DCMPG else asm.Opcodes.DCMPL) } bc.emitIF(op, success) } @@ -1134,8 +1131,8 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { } /* Emits code to compare (and consume) stack-top and zero using the 'op' operator */ - private def genCZJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label) { - if (targetIfNoJump == success) genCZJUMP(failure, success, op.negate, tk, targetIfNoJump) + private def genCZJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label, negated: Boolean = false) { + if (targetIfNoJump == success) genCZJUMP(failure, success, op.negate, tk, targetIfNoJump, negated = !negated) else { if (tk.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT bc.emitIF(op, success) @@ -1145,18 +1142,17 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { case TestOp.NE => bc emitIFNONNULL success } } else { + def useCmpG = if (negated) op == TestOp.GT || op == TestOp.GE else op == TestOp.LT || op == TestOp.LE (tk: @unchecked) match { case LONG => emit(asm.Opcodes.LCONST_0) emit(asm.Opcodes.LCMP) case FLOAT => emit(asm.Opcodes.FCONST_0) - if (op == TestOp.LT || op == TestOp.LE) emit(asm.Opcodes.FCMPG) - else emit(asm.Opcodes.FCMPL) + emit(if (useCmpG) asm.Opcodes.FCMPG else asm.Opcodes.FCMPL) case DOUBLE => emit(asm.Opcodes.DCONST_0) - if (op == TestOp.LT || op == TestOp.LE) emit(asm.Opcodes.DCMPG) - else emit(asm.Opcodes.DCMPL) + emit(if (useCmpG) asm.Opcodes.DCMPG else asm.Opcodes.DCMPL) } bc.emitIF(op, success) } @@ -1171,8 +1167,8 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { case scalaPrimitives.NE => TestOp.NE case scalaPrimitives.LT => TestOp.LT case scalaPrimitives.LE => TestOp.LE - case scalaPrimitives.GE => TestOp.GE case scalaPrimitives.GT => TestOp.GT + case scalaPrimitives.GE => TestOp.GE } /** Some useful equality helpers. */ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index a5744983b280..5a5747c81f65 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -1336,6 +1336,7 @@ object BCodeHelpers { } object TestOp { + // the order here / op numbers are important to get the correct result when calling opcodeIF val EQ = new TestOp(0) val NE = new TestOp(1) val LT = new TestOp(2) diff --git a/test/junit/scala/lang/primitives/NaNTest.scala b/test/junit/scala/lang/primitives/NaNTest.scala new file mode 100644 index 000000000000..f4c42583952e --- /dev/null +++ b/test/junit/scala/lang/primitives/NaNTest.scala @@ -0,0 +1,38 @@ +package scala.lang.primitives + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.testing.RunTesting + +@RunWith(classOf[JUnit4]) +class NaNTest extends RunTesting { + + @Test + def compNaNFalse(): Unit = { + def code(tp: String) = + s"""val n = $tp.NaN + |def ne(x: $tp, y: $tp) = x != y + |val fs: List[($tp, $tp) => Boolean] = List(_ < _, _ <= _, _ > _, _ >= _, _ == _, (x, y) => !ne(x, y)) + |val vs = List[$tp](n, 1, -1, 0) + |for (f <- fs; v <- vs; (x, y) <- List((n, v), (v, n))) yield f(x, y) + """.stripMargin + + runner.run[List[Boolean]](code("Double")).foreach(assertFalse) + runner.run[List[Boolean]](code("Float")).foreach(assertFalse) + } + + @Test + def genericEqNe(): Unit = { + def code(tp: String) = + s"""def a[T](x: T, y: T) = x == y + |def b[T](x: T, y: T) = x != y + |val n = $tp.NaN + |a(n, n) :: a(n, 0) :: a (0, n) :: !b(n, n) :: !b(n, 0) :: !b(0, n) :: Nil + """.stripMargin + runner.run[List[Boolean]](code("Double")).foreach(assertFalse) + runner.run[List[Boolean]](code("Float")).foreach(assertFalse) + } +} From bd588ff2191ea71eab251c16b8ca5228bf02d0b1 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 2 Jun 2016 09:05:47 +0200 Subject: [PATCH 086/153] scala version in benchmark project --- test/benchmarks/build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/build.sbt b/test/benchmarks/build.sbt index 4806ecdde80c..31cee701ad61 100644 --- a/test/benchmarks/build.sbt +++ b/test/benchmarks/build.sbt @@ -1,5 +1,5 @@ scalaHome := Some(file("../../build/pack")) -scalaVersion := "2.11.8" +scalaVersion := "2.12.0-dev" scalacOptions ++= Seq("-feature", "-Yopt:l:classpath") lazy val root = (project in file(".")). From fe61bcf99c0c10054066f7ff41e4c7f44cf02e5d Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 27 May 2016 14:43:22 -0700 Subject: [PATCH 087/153] SI-9104 Autodetect raw pastage If `-raw` is not supplied explicitly to REPL `:paste`, see if the code text starts with `package` keyword or else see if it parses to a named package (to cope with leading commentary). In that case, take it as raw. But parse only on suspect comment slash. It's only worth parsing for a package if there's a chance that package keyword is buried behind comments. Small refactors to the `paste` object. --- .../scala/tools/nsc/interpreter/ILoop.scala | 45 +++++++++++-------- .../scala/tools/nsc/interpreter/IMain.scala | 16 +++++-- test/files/run/repl-paste-b.check | 14 ++++++ test/files/run/repl-paste-b.scala | 13 ++++++ test/files/run/repl-paste-raw-b.pastie | 8 ++++ test/files/run/repl-paste-raw-b.scala | 18 ++++++++ test/files/run/repl-paste-raw-c.pastie | 5 +++ test/files/run/repl-paste-raw-c.scala | 16 +++++++ test/files/run/repl-paste-raw.pastie | 4 +- test/files/run/repl-paste-raw.scala | 2 +- 10 files changed, 117 insertions(+), 24 deletions(-) create mode 100644 test/files/run/repl-paste-b.check create mode 100644 test/files/run/repl-paste-b.scala create mode 100644 test/files/run/repl-paste-raw-b.pastie create mode 100644 test/files/run/repl-paste-raw-b.scala create mode 100644 test/files/run/repl-paste-raw-c.pastie create mode 100644 test/files/run/repl-paste-raw-c.scala diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 8f19b4860a2d..66a5f08e964b 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -490,11 +490,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) def editCommand(what: String): Result = editCommand(what, Properties.envOrNone("EDITOR")) def editCommand(what: String, editor: Option[String]): Result = { - def diagnose(code: String) = { - echo("The edited code is incomplete!\n") - val errless = intp compileSources new BatchSourceFile("", s"object pastel {\n$code\n}") - if (errless) echo("The compiler reports no errors.") - } + def diagnose(code: String): Unit = paste.incomplete("The edited code is incomplete!\n", "", code) def edit(text: String): Result = editor match { case Some(ed) => @@ -756,21 +752,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) text } def interpretCode() = { - val res = intp.withLabel(label)(intp interpret code) - // if input is incomplete, let the compiler try to say why - if (res == IR.Incomplete) { - echo("The pasted code is incomplete!\n") - // Remembrance of Things Pasted in an object - val errless = intp compileSources new BatchSourceFile(label, s"object pastel {\n$code\n}") - if (errless) echo("...but compilation found no error? Good luck with that.") - } - } - def compileCode() = { - val errless = intp compileSources new BatchSourceFile(label, code) - if (!errless) echo("There were compilation errors!") + if (intp.withLabel(label)(intp interpret code) == IR.Incomplete) + paste.incomplete("The pasted code is incomplete!\n", label, code) } + def compileCode() = paste.compilePaste(label = label, code = code) + if (code.nonEmpty) { - if (raw) compileCode() else interpretCode() + if (raw || paste.isPackaged(code)) compileCode() else interpretCode() } result } @@ -778,6 +766,27 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) private object paste extends Pasted(prompt) { def interpret(line: String) = intp interpret line def echo(message: String) = ILoop.this echo message + + val leadingElement = raw"(?s)\s*(package\s|/)".r + def isPackaged(code: String): Boolean = { + leadingElement.findPrefixMatchOf(code) + .map(m => if (m.group(1) == "/") intp.parse.packaged(code) else true) + .getOrElse(false) + } + + // if input is incomplete, wrap and compile for diagnostics. + def incomplete(message: String, label: String, code: String): Boolean = { + echo(message) + val errless = intp.compileSources(new BatchSourceFile(label, s"object pastel {\n$code\n}")) + if (errless) echo("No error found in incomplete source.") + errless + } + + def compilePaste(label: String, code: String): Boolean = { + val errless = intp.compileSources(new BatchSourceFile(label, code)) + if (!errless) echo("There were compilation errors!") + errless + } } private object invocation { diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 2f20a1cd0aff..44784aa9534b 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -1101,7 +1101,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends case class Incomplete(trees: List[Tree]) extends Result case class Success(trees: List[Tree]) extends Result - def apply(line: String): Result = debugging(s"""parse("$line")""") { + def apply(line: String): Result = debugging(s"""parse("$line")""") { var isIncomplete = false def parse = { reporter.reset() @@ -1110,8 +1110,18 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends else if (isIncomplete) Incomplete(trees) else Success(trees) } - currentRun.parsing.withIncompleteHandler((_, _) => isIncomplete = true) {parse} - + currentRun.parsing.withIncompleteHandler((_, _) => isIncomplete = true)(parse) + } + // code has a named package + def packaged(line: String): Boolean = { + def parses = { + reporter.reset() + val tree = newUnitParser(line).parse() + !reporter.hasErrors && { + tree match { case PackageDef(Ident(id), _) => id != nme.EMPTY_PACKAGE_NAME case _ => false } + } + } + beSilentDuring(parses) } } diff --git a/test/files/run/repl-paste-b.check b/test/files/run/repl-paste-b.check new file mode 100644 index 000000000000..2e205d48d65f --- /dev/null +++ b/test/files/run/repl-paste-b.check @@ -0,0 +1,14 @@ + +scala> :paste < EOF +// Entering paste mode (EOF to finish) + +object X +EOF + +// Exiting paste mode, now interpreting. + +defined object X + +scala> assert(X.getClass.getName.contains("line")) + +scala> :quit diff --git a/test/files/run/repl-paste-b.scala b/test/files/run/repl-paste-b.scala new file mode 100644 index 000000000000..718f7d9e1703 --- /dev/null +++ b/test/files/run/repl-paste-b.scala @@ -0,0 +1,13 @@ +import scala.tools.partest.ReplTest + +// confirm X not in empty package +object Test extends ReplTest { + def code = + """ +:paste < EOF +object X +EOF +assert(X.getClass.getName.contains("line")) +""" + +} diff --git a/test/files/run/repl-paste-raw-b.pastie b/test/files/run/repl-paste-raw-b.pastie new file mode 100644 index 000000000000..f13b4bcf8bdb --- /dev/null +++ b/test/files/run/repl-paste-raw-b.pastie @@ -0,0 +1,8 @@ + +// a raw paste is not a script +// hence it can be packaged + +package brown_paper + +// these are a few of my favorite things +case class Gift (hasString: Boolean) diff --git a/test/files/run/repl-paste-raw-b.scala b/test/files/run/repl-paste-raw-b.scala new file mode 100644 index 000000000000..d1c7692f2f7f --- /dev/null +++ b/test/files/run/repl-paste-raw-b.scala @@ -0,0 +1,18 @@ + +import scala.tools.partest.SessionTest + +object Test extends SessionTest { + def session = +s"""| + |scala> :paste $pastie + |Pasting file $pastie... + | + |scala> val favoriteThing = brown_paper.Gift(true) + |favoriteThing: brown_paper.Gift = Gift(true) + | + |scala> favoriteThing.hasString + |res0: Boolean = true + | + |scala> :quit""" + def pastie = testPath changeExtension "pastie" +} diff --git a/test/files/run/repl-paste-raw-c.pastie b/test/files/run/repl-paste-raw-c.pastie new file mode 100644 index 000000000000..364d8cef4be6 --- /dev/null +++ b/test/files/run/repl-paste-raw-c.pastie @@ -0,0 +1,5 @@ + +// not actually a candidate for raw paste + +val nope = 42 + diff --git a/test/files/run/repl-paste-raw-c.scala b/test/files/run/repl-paste-raw-c.scala new file mode 100644 index 000000000000..600ac4d2f084 --- /dev/null +++ b/test/files/run/repl-paste-raw-c.scala @@ -0,0 +1,16 @@ + +import scala.tools.partest.SessionTest + +object Test extends SessionTest { + def session = +s"""| + |scala> :paste -raw $pastie + |Pasting file $pastie... + |$pastie:3: error: expected class or object definition + |val nope = 42 + |^ + |There were compilation errors! + | + |scala> :quit""" + def pastie = testPath changeExtension "pastie" +} diff --git a/test/files/run/repl-paste-raw.pastie b/test/files/run/repl-paste-raw.pastie index f13b4bcf8bdb..a4a570aaa2cf 100644 --- a/test/files/run/repl-paste-raw.pastie +++ b/test/files/run/repl-paste-raw.pastie @@ -1,8 +1,8 @@ +package brown_paper + // a raw paste is not a script // hence it can be packaged -package brown_paper - // these are a few of my favorite things case class Gift (hasString: Boolean) diff --git a/test/files/run/repl-paste-raw.scala b/test/files/run/repl-paste-raw.scala index 9bd5e8e63e12..d1c7692f2f7f 100644 --- a/test/files/run/repl-paste-raw.scala +++ b/test/files/run/repl-paste-raw.scala @@ -4,7 +4,7 @@ import scala.tools.partest.SessionTest object Test extends SessionTest { def session = s"""| - |scala> :paste -raw $pastie + |scala> :paste $pastie |Pasting file $pastie... | |scala> val favoriteThing = brown_paper.Gift(true) From f07019ffa56ec2dfab8ab0d9a83133005761a877 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 15 Apr 2016 14:05:02 +1000 Subject: [PATCH 088/153] SI-9390 Avoid needless outer capture with local classes An existing optimization in `Constructors` elides the outer field in member and local classes, if the class doesn't use the outer reference. (Member classes also need to be final, which is a secret handshake to say we're also happy to weaken prefix matching in the pattern matcher.) That optimization leaves the constructor signature as is: the constructor still accepts the outer instance, but does not store it. For member classes, this means that we can separately compile code that calls the constructor. Local classes need not be hampered by this constraint, we could remove the outer instance from the constructor call too. Why would we want to do this? Let's look at the case before and after this commit. Before: ``` class C extends Object { def foo(): Function1 = $anonfun(); final def $anonfun$foo$1($this: C, x: Object): Object = new <$anon: Object>($this); def (): C = { C.super.(); () } }; final class anon$1 extends Object { def ($outer: C): <$anon: Object> = { anon$1.super.(); () } } ``` After: ``` class C extends Object { def foo(): Function1 = $anonfun(); final def $anonfun$foo$1(x: Object): Object = new <$anon: Object>(null); def (): C = { C.super.(); () } }; final class anon$1 extends Object { def ($outer: C): <$anon: Object> = { anon$1.super.(); () } } ``` However, the status quo means that a lambda that This in turn makes lambdas that refer to such classes serializable even when the outer class is not itself serialiable. I have not attempted to extend this to calls to secondary constructors. --- .../tools/nsc/transform/Constructors.scala | 3 +++ .../tools/nsc/transform/Delambdafy.scala | 8 +++++++ .../tools/nsc/transform/ExplicitOuter.scala | 4 +--- .../reflect/internal/StdAttachments.scala | 5 +++++ .../scala/reflect/internal/StdNames.scala | 1 + .../scala/reflect/internal/Symbols.scala | 3 +++ .../reflect/runtime/JavaUniverseForce.scala | 1 + test/files/jvm/t9105.check | 14 ++----------- test/files/run/t9390c.scala | 21 +++++++++++++++++++ test/files/run/t9390d.scala | 12 +++++++++++ 10 files changed, 57 insertions(+), 15 deletions(-) create mode 100644 test/files/run/t9390c.scala create mode 100644 test/files/run/t9390d.scala diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 636fb08b89ef..971a55f763c8 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -715,6 +715,9 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { primaryConstrBody.expr) }) + if (omittableAccessor.exists(_.isOuterField) && !constructorStats.exists(_.exists { case i: Ident if i.symbol.isOuterParam => true; case _ => false})) + primaryConstructor.symbol.updateAttachment(OuterArgCanBeElided) + val constructors = primaryConstructor :: auxConstructors // Unlink all fields that can be dropped from class scope diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index a8933a9ee6b9..2dd8def53e13 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -279,10 +279,15 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre if (!dd.symbol.hasFlag(STATIC) && !methodReferencesThis(dd.symbol)) dd.symbol.setFlag(STATIC) super.transform(tree) + case Apply(fun, outer :: rest) if shouldElideOuterArg(fun.symbol, outer) => + val nullOuter = gen.mkZero(outer.tpe) + treeCopy.Apply(tree, transform(fun), nullOuter :: transformTrees(rest)) case _ => super.transform(tree) } } // DelambdafyTransformer + private def shouldElideOuterArg(fun: Symbol, outerArg: Tree): Boolean = + fun.isConstructor && treeInfo.isQualifierSafeToElide(outerArg) && fun.hasAttachment[OuterArgCanBeElided.type] // A traverser that finds symbols used but not defined in the given Tree // TODO freeVarTraverser in LambdaLift does a very similar task. With some @@ -368,6 +373,9 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre case Apply(sel @ Select(This(_), _), args) if sel.symbol.isLiftedMethod => if (currentMethod.exists) liftedMethodReferences(currentMethod) += sel.symbol super.traverseTrees(args) + case Apply(fun, outer :: rest) if shouldElideOuterArg(fun.symbol, outer) => + super.traverse(fun) + super.traverseTrees(rest) case This(_) => if (currentMethod.exists && tree.symbol == currentMethod.enclClass) { debuglog(s"$currentMethod directly refers to 'this'") diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 3d6fad4238ac..411ff6b9bec2 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -67,8 +67,6 @@ abstract class ExplicitOuter extends InfoTransform result } - private val innerClassConstructorParamName: TermName = newTermName("arg" + nme.OUTER) - class RemoveBindingsTransformer(toRemove: Set[Symbol]) extends Transformer { override def transform(tree: Tree) = tree match { case Bind(_, body) if toRemove(tree.symbol) => super.transform(body) @@ -169,7 +167,7 @@ abstract class ExplicitOuter extends InfoTransform val paramsWithOuter = if (sym.isClassConstructor && isInner(sym.owner)) // 1 - sym.newValueParameter(innerClassConstructorParamName, sym.pos).setInfo(sym.owner.outerClass.thisType) :: params + sym.newValueParameter(nme.OUTER_ARG, sym.pos).setInfo(sym.owner.outerClass.thisType) :: params else params if ((resTpTransformed ne resTp) || (paramsWithOuter ne params)) MethodType(paramsWithOuter, resTpTransformed) diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index ef95b3884317..76e34153c9f1 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -71,4 +71,9 @@ trait StdAttachments { abstract class InlineAnnotatedAttachment case object NoInlineCallsiteAttachment extends InlineAnnotatedAttachment case object InlineCallsiteAttachment extends InlineAnnotatedAttachment + + /** Attached to a local class that has its outer field elided. A `null` constant may be passed + * in place of the outer parameter, can help callers to avoid capturing the outer instance. + */ + case object OuterArgCanBeElided extends PlainAttachment } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index c93ecac3fad8..d96d06ca9411 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -364,6 +364,7 @@ trait StdNames { val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$" val OUTER: NameType = "$outer" val OUTER_LOCAL: NameType = OUTER.localName + val OUTER_ARG: NameType = "arg" + OUTER val OUTER_SYNTH: NameType = "" // emitted by virtual pattern matcher, replaced by outer accessor in explicitouter val ROOTPKG: NameType = "_root_" val SELECTOR_DUMMY: NameType = "" diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 3b886d357fde..e2fb82718698 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -914,6 +914,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Is this symbol an accessor method for outer? */ final def isOuterField = isArtifact && (unexpandedName == nme.OUTER_LOCAL) + /** Is this symbol an outer parameter in a constructor */ + final def isOuterParam = isParameter && owner.isConstructor && (name == nme.OUTER_ARG || name == nme.OUTER) + /** Does this symbol denote a stable value, ignoring volatility? * * Stability and volatility are checked separately to allow volatile paths in patterns that amount to equality checks. SI-6815 diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 28222cf9a7fd..0a90a141d3c0 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -45,6 +45,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.SubpatternsAttachment this.NoInlineCallsiteAttachment this.InlineCallsiteAttachment + this.OuterArgCanBeElided this.noPrint this.typeDebug this.Range diff --git a/test/files/jvm/t9105.check b/test/files/jvm/t9105.check index 48439ee004fb..9447e0cf2916 100644 --- a/test/files/jvm/t9105.check +++ b/test/files/jvm/t9105.check @@ -1,18 +1,8 @@ -#partest -Ydelambdafy:inline -(class C$$anonfun$1$A$1,class C$$anonfun$1,null) -(class C$$anonfun$1$B$1,class C$$anonfun$1,private final java.lang.Object C$$anonfun$1.m$1()) -(class C$$anonfun$1$C$1,class C$$anonfun$1,null) -(class C$$anonfun$1$$anonfun$2$D$1,class C$$anonfun$1$$anonfun$2,null) -(class C$$anonfun$met$1$E$1,class C$$anonfun$met$1,null) -(class C$$anonfun$met$1$F$1,class C$$anonfun$met$1,private final java.lang.Object C$$anonfun$met$1.m$2()) -(class C$$anonfun$met$1$G$1,class C$$anonfun$met$1,null) -(class C$$anonfun$met$1$$anonfun$3$H$1,class C$$anonfun$met$1$$anonfun$3,null) -#partest !-Ydelambdafy:inline (class C$A$1,class C,null) -(class C$B$1,class C,private final java.lang.Object C.m$1()) +(class C$B$1,class C,private static final java.lang.Object C.m$1()) (class C$C$1,class C,null) (class C$D$1,class C,null) (class C$E$1,class C,public scala.Function0 C.met()) -(class C$F$1,class C,private final java.lang.Object C.m$2()) +(class C$F$1,class C,private static final java.lang.Object C.m$2()) (class C$G$1,class C,public scala.Function0 C.met()) (class C$H$1,class C,public scala.Function0 C.met()) diff --git a/test/files/run/t9390c.scala b/test/files/run/t9390c.scala new file mode 100644 index 000000000000..db39da57cddd --- /dev/null +++ b/test/files/run/t9390c.scala @@ -0,0 +1,21 @@ +class C { // C is not serializable + def foo = { + { (x: Any) => new Object {} } + } +} +object Test { + def main(args: Array[String]): Unit = { + val c = new C + val f = c.foo + val f1 = serializeDeserialize(f) + } + + def serializeDeserialize[T <: AnyRef](obj: T): T = { + import java.io._ + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } +} diff --git a/test/files/run/t9390d.scala b/test/files/run/t9390d.scala new file mode 100644 index 000000000000..3c5de3abf73d --- /dev/null +++ b/test/files/run/t9390d.scala @@ -0,0 +1,12 @@ +class C { // C is not serializable + def foo: () => Any = { + { () => class UseOuterInConstructor { C.this.toString }; new UseOuterInConstructor : Any} + } +} +object Test { + def main(args: Array[String]): Unit = { + val c = new C + val f = c.foo + f() // Doesn't NPE, as we didn't elide the outer instance in the constructor call. + } +} From 5667ff46c134878e35edca1ff57b8007ebec4f9a Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 2 Jun 2016 18:53:04 -0700 Subject: [PATCH 089/153] Prohibit @native method in trait On the JVM, a @native interface method results in a VerifyError. Other platforms could decide to be more permissive, but it seems like allowing them in classes is enough. --- .../tools/nsc/typechecker/RefChecks.scala | 28 ++++++++++++------- src/library/scala/native.scala | 9 ++++-- test/files/neg/trait-no-native.check | 4 +++ test/files/neg/trait-no-native.scala | 4 +++ 4 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 test/files/neg/trait-no-native.check create mode 100644 test/files/neg/trait-no-native.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index a5a680d13523..d1764ea4829e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1659,24 +1659,32 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // inside annotations. applyRefchecksToAnnotations(tree) var result: Tree = tree match { - case DefDef(_, _, _, _, _, EmptyTree) if sym hasAnnotation NativeAttr => - sym resetFlag DEFERRED - transform(deriveDefDef(tree)(_ => typed(gen.mkSysErrorCall("native method stub")))) - - case ValDef(_, _, _, _) | DefDef(_, _, _, _, _, _) => + case vod: ValOrDefDef => checkDeprecatedOvers(tree) - checkInfiniteLoop(tree.asInstanceOf[ValOrDefDef]) + checkInfiniteLoop(vod) if (settings.warnNullaryUnit) checkNullaryMethodReturnType(sym) if (settings.warnInaccessible) { if (!sym.isConstructor && !sym.isEffectivelyFinalOrNotOverridden && !sym.isSynthetic) checkAccessibilityOfReferencedTypes(tree) } - tree match { - case dd: DefDef => checkByNameRightAssociativeDef(dd) - case _ => + vod match { + case dd: DefDef => + checkByNameRightAssociativeDef(dd) + + if (sym hasAnnotation NativeAttr) { + if (sym.owner.isTrait) { + reporter.error(tree.pos, "A trait cannot define a native method.") + tree + } else if (dd.rhs == EmptyTree) { + // pretend it had a stub implementation + sym resetFlag DEFERRED + deriveDefDef(dd)(_ => typed(gen.mkSysErrorCall("native method stub"))) + } else tree + } else tree + + case _ => tree } - tree case Template(parents, self, body) => localTyper = localTyper.atOwner(tree, currentOwner) diff --git a/src/library/scala/native.scala b/src/library/scala/native.scala index dbacc7861862..49d3ced805dd 100644 --- a/src/library/scala/native.scala +++ b/src/library/scala/native.scala @@ -16,8 +16,11 @@ package scala * @native def f(x: Int, y: List[Long]): String = ... * }}} * - * Method body is not generated if method is marked with `@native`, - * but it is type checked when present. + * A `@native` method is compiled to the platform's native method, + * while discarding the method's body (if any). The body will be type checked if present. * - * @since 2.6 */ + * A method marked @native must be a member of a class, not a trait (since 2.12). + * + * @since 2.6 + */ class native extends scala.annotation.StaticAnnotation {} diff --git a/test/files/neg/trait-no-native.check b/test/files/neg/trait-no-native.check new file mode 100644 index 000000000000..12bce4042dda --- /dev/null +++ b/test/files/neg/trait-no-native.check @@ -0,0 +1,4 @@ +trait-no-native.scala:3: error: A trait cannot define a native method. + @native def foo = ??? + ^ +one error found diff --git a/test/files/neg/trait-no-native.scala b/test/files/neg/trait-no-native.scala new file mode 100644 index 000000000000..463e604a48b7 --- /dev/null +++ b/test/files/neg/trait-no-native.scala @@ -0,0 +1,4 @@ +trait T { + // should not compile, because it would result in a VerifyError + @native def foo = ??? +} From be9c0febd65875615b318209e0aa994eb76c2011 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 18 Aug 2015 10:11:29 +0200 Subject: [PATCH 090/153] SI-9737 [no-merge] Backport stringOf ParIterable Cherry-picked c5f3d3f286ee5c26c8ddcf10f6878058e8f7e040 Edited comment: in stringOf, let GenIterable subsume both Iterable and ParIterable. This change is required for Scala.js compatibility as it does not support parallel collections. Conflicts: src/library/scala/runtime/ScalaRunTime.scala --- src/library/scala/runtime/ScalaRunTime.scala | 4 +- .../scala/runtime/ScalaRunTimeTest.scala | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index 20f067f34f6f..026d5edd293f 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -9,7 +9,7 @@ package scala package runtime -import scala.collection.{ Seq, IndexedSeq, TraversableView, AbstractIterator } +import scala.collection.{ Seq, IndexedSeq, TraversableView, AbstractIterator, GenIterable } import scala.collection.mutable.WrappedArray import scala.collection.immutable.{ StringLike, NumericRange, List, Stream, Nil, :: } import scala.collection.generic.{ Sorted, IsTraversableLike } @@ -325,7 +325,7 @@ object ScalaRunTime { case x if useOwnToString(x) => x.toString case x: AnyRef if isArray(x) => arrayToString(x) case x: scala.collection.Map[_, _] => x.iterator take maxElements map mapInner mkString (x.stringPrefix + "(", ", ", ")") - case x: Iterable[_] => x.iterator take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")") + case x: GenIterable[_] => x.iterator take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")") case x: Traversable[_] => x take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")") case x: Product1[_] if isTuple(x) => "(" + inner(x._1) + ",)" // that special trailing comma case x: Product if isTuple(x) => x.productIterator map inner mkString ("(", ",", ")") diff --git a/test/junit/scala/runtime/ScalaRunTimeTest.scala b/test/junit/scala/runtime/ScalaRunTimeTest.scala index 9da197c71ace..e28deae786e2 100644 --- a/test/junit/scala/runtime/ScalaRunTimeTest.scala +++ b/test/junit/scala/runtime/ScalaRunTimeTest.scala @@ -67,4 +67,61 @@ class ScalaRunTimeTest { val c = new C() assertFalse(c.toString, isTuple(c)) } + + @Test + def testStringOf() { + import ScalaRunTime.stringOf + import scala.collection._ + import parallel.ParIterable + + assertEquals("null", stringOf(null)) + assertEquals( "\"\"", stringOf("")) + + assertEquals("abc", stringOf("abc")) + assertEquals("\" abc\"", stringOf(" abc")) + assertEquals("\"abc \"", stringOf("abc ")) + + assertEquals("""Array()""", stringOf(Array.empty[AnyRef])) + assertEquals("""Array()""", stringOf(Array.empty[Int])) + assertEquals("""Array(1, 2, 3)""", stringOf(Array(1, 2, 3))) + assertEquals("""Array(a, "", " c", null)""", stringOf(Array("a", "", " c", null))) + assertEquals("""Array(Array("", 1, Array(5)), Array(1))""", + stringOf(Array(Array("", 1, Array(5)), Array(1)))) + + val map = Map(1->"", 2->"a", 3->" a", 4->null) + assertEquals(s"""${map.stringPrefix}(1 -> "", 2 -> a, 3 -> " a", 4 -> null)""", stringOf(map)) + assertEquals(s"""${map.stringPrefix}(1 -> "", 2 -> a)""", stringOf(map, 2)) + + val iterable = Iterable("a", "", " c", null) + assertEquals(s"""${iterable.stringPrefix}(a, "", " c", null)""", stringOf(iterable)) + assertEquals(s"""${iterable.stringPrefix}(a, "")""", stringOf(iterable, 2)) + + val parIterable = ParIterable("a", "", " c", null) + assertEquals(s"""${parIterable.stringPrefix}(a, "", " c", null)""", stringOf(parIterable)) + assertEquals(s"""${parIterable.stringPrefix}(a, "")""", stringOf(parIterable, 2)) + + val traversable = new Traversable[Int] { + def foreach[U](f: Int => U): Unit = (0 to 3).foreach(f) + } + assertEquals(s"${traversable.stringPrefix}(0, 1, 2, 3)", stringOf(traversable)) + assertEquals(s"${traversable.stringPrefix}(0, 1)", stringOf(traversable, 2)) + + val tuple1 = Tuple1(0) + assertEquals("(0,)", stringOf(tuple1)) + assertEquals("(0,)", stringOf(tuple1, 0)) + + val tuple2 = Tuple2(0, 1) + assertEquals("(0,1)", stringOf(tuple2)) + assertEquals("(0,1)", stringOf(tuple2, 0)) + + val tuple3 = Tuple3(0, 1, 2) + assertEquals("(0,1,2)", stringOf(tuple3)) + assertEquals("(0,1,2)", stringOf(tuple3, 0)) + + val x = new Object { + override def toString(): String = "this is the stringOf string" + } + assertEquals(stringOf(x), "this is the stringOf string") + assertEquals(stringOf(x, 2), "this is the stringOf string") + } } From a23f6a7ba2c20096837a8d254a42d2bedd620f15 Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Sat, 4 Jun 2016 12:47:52 +0100 Subject: [PATCH 091/153] Remove experimental status from sbt build in load message sbt is now the preferred build tool. --- build.sbt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 0194bc08b6a8..9fcfa01161b8 100644 --- a/build.sbt +++ b/build.sbt @@ -700,9 +700,7 @@ lazy val root = (project in file(".")) scaladoc, scalap, partestExtras, junit, libraryAll, scalaDist).settings( sources in Compile := Seq.empty, onLoadMessage := """|*** Welcome to the sbt build definition for Scala! *** - |This build definition has an EXPERIMENTAL status. If you are not - |interested in testing or working on the build itself, please use - |the Ant build definition for now. Check README.md for more information.""".stripMargin + |Check README.md for more information.""".stripMargin ) // The following subprojects' binaries are required for building "pack": From fcf17beee7304928cb97c4902a2e2833091d3a8f Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 4 Jun 2016 15:11:26 -0700 Subject: [PATCH 092/153] SI-7898 Preserve reader against subversion SBT tries to install its own SimpleReader (for some reason) if it needs to create its own IMain. Because Rube Goldberg needs to execute some postinit hooks, don't let SBT do that. --- src/repl/scala/tools/nsc/interpreter/ILoop.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 7dab371cafd6..b086b2181e70 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -966,7 +966,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) // while we go fire up the REPL try { - createInterpreter() + // don't allow ancient sbt to hijack the reader + savingReader { + createInterpreter() + } intp.initializeSynchronous() globalFuture = Future successful true if (intp.reporter.hasErrors) { From 1f812e9482855d3fd5a8a5e9118942dc80f22db5 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 30 May 2016 14:38:50 +0200 Subject: [PATCH 093/153] Avoid separate traversal in inliner to remove line number nodes --- .../tools/nsc/backend/jvm/analysis/BackendUtils.scala | 10 ++++++---- .../scala/tools/nsc/backend/jvm/opt/Inliner.scala | 6 +----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index 6d3c3f3863c2..9abd1d80067d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -98,7 +98,7 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { * a boolean indicating if the instruction list contains an instantiation of a serializable SAM * type. */ - def cloneInstructions(methodNode: MethodNode, labelMap: Map[LabelNode, LabelNode]): (InsnList, Map[AbstractInsnNode, AbstractInsnNode], Boolean) = { + def cloneInstructions(methodNode: MethodNode, labelMap: Map[LabelNode, LabelNode], keepLineNumbers: Boolean): (InsnList, Map[AbstractInsnNode, AbstractInsnNode], Boolean) = { val javaLabelMap = labelMap.asJava val result = new InsnList var map = Map.empty[AbstractInsnNode, AbstractInsnNode] @@ -112,9 +112,11 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { } case _ => } - val cloned = ins.clone(javaLabelMap) - result add cloned - map += ((ins, cloned)) + if (keepLineNumbers || !ins.isInstanceOf[LineNumberNode]) { + val cloned = ins.clone(javaLabelMap) + result add cloned + map += ((ins, cloned)) + } } (result, map, hasSerializableClosureInstantiation) } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index 809b9e310dce..d18963ec8bbd 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -268,11 +268,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { // New labels for the cloned instructions val labelsMap = cloneLabels(callee) - val (clonedInstructions, instructionMap, hasSerializableClosureInstantiation) = cloneInstructions(callee, labelsMap) - val keepLineNumbers = callsiteClass == calleeDeclarationClass - if (!keepLineNumbers) { - removeLineNumberNodes(clonedInstructions) - } + val (clonedInstructions, instructionMap, hasSerializableClosureInstantiation) = cloneInstructions(callee, labelsMap, keepLineNumbers = callsiteClass == calleeDeclarationClass) // local vars in the callee are shifted by the number of locals at the callsite val localVarShift = callsiteMethod.maxLocals From 037a089ad4fb7137513777ccda6d47e30e151838 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 30 May 2016 19:25:14 +0200 Subject: [PATCH 094/153] Store source file paths of classes being compiled in the bytecode repo For classes being compiled (vs. being loaded from classfiles), keep the source file path in the bytecode repo. This will allow to keep line numbers when inlining from one class into another in case the two are defined in the same compilation unit. --- .../tools/nsc/backend/jvm/GenBCode.scala | 25 ++++--- .../backend/jvm/opt/ByteCodeRepository.scala | 67 +++++++++---------- .../tools/nsc/backend/jvm/opt/CallGraph.scala | 25 +++---- .../backend/jvm/opt/ClosureOptimizer.scala | 8 +-- .../backend/jvm/opt/InlinerHeuristics.scala | 10 +-- .../jvm/opt/InlinerIllegalAccessTest.scala | 2 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 2 +- 7 files changed, 67 insertions(+), 72 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala index 02dc2b8edea2..584b11d4edac 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala @@ -77,15 +77,16 @@ abstract class GenBCode extends BCodeSyncAndTry { /* ---------------- q2 ---------------- */ - case class Item2(arrivalPos: Int, - mirror: asm.tree.ClassNode, - plain: asm.tree.ClassNode, - bean: asm.tree.ClassNode, - outFolder: scala.tools.nsc.io.AbstractFile) { + case class Item2(arrivalPos: Int, + mirror: asm.tree.ClassNode, + plain: asm.tree.ClassNode, + bean: asm.tree.ClassNode, + sourceFilePath: String, + outFolder: scala.tools.nsc.io.AbstractFile) { def isPoison = { arrivalPos == Int.MaxValue } } - private val poison2 = Item2(Int.MaxValue, null, null, null, null) + private val poison2 = Item2(Int.MaxValue, null, null, null, null, null) private val q2 = new _root_.java.util.LinkedList[Item2] /* ---------------- q3 ---------------- */ @@ -205,6 +206,7 @@ abstract class GenBCode extends BCodeSyncAndTry { val item2 = Item2(arrivalPos, mirrorC, plainC, beanC, + cunit.source.file.canonicalPath, outF) q2 add item2 // at the very end of this method so that no Worker2 thread starts mutating before we're done. @@ -226,10 +228,11 @@ abstract class GenBCode extends BCodeSyncAndTry { // add classes to the bytecode repo before building the call graph: the latter needs to // look up classes and methods in the code repo. if (settings.optAddToBytecodeRepository) q2.asScala foreach { - case Item2(_, mirror, plain, bean, _) => - if (mirror != null) byteCodeRepository.add(mirror, ByteCodeRepository.CompilationUnit) - if (plain != null) byteCodeRepository.add(plain, ByteCodeRepository.CompilationUnit) - if (bean != null) byteCodeRepository.add(bean, ByteCodeRepository.CompilationUnit) + case Item2(_, mirror, plain, bean, sourceFilePath, _) => + val someSourceFilePath = Some(sourceFilePath) + if (mirror != null) byteCodeRepository.add(mirror, someSourceFilePath) + if (plain != null) byteCodeRepository.add(plain, someSourceFilePath) + if (bean != null) byteCodeRepository.add(bean, someSourceFilePath) } if (settings.optBuildCallGraph) q2.asScala foreach { item => // skip call graph for mirror / bean: wd don't inline into tem, and they are not used in the plain class @@ -286,7 +289,7 @@ abstract class GenBCode extends BCodeSyncAndTry { cw.toByteArray } - val Item2(arrivalPos, mirror, plain, bean, outFolder) = item + val Item2(arrivalPos, mirror, plain, bean, _, outFolder) = item val mirrorC = if (mirror == null) null else SubItem3(mirror.name, getByteArray(mirror)) val plainC = SubItem3(plain.name, getByteArray(plain)) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala index 16590ec75c58..78acd72dbab6 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala @@ -15,7 +15,6 @@ import scala.tools.asm.Attribute import scala.tools.nsc.backend.jvm.BackendReporting._ import scala.tools.nsc.util.ClassPath import BytecodeUtils._ -import ByteCodeRepository._ import BTypes.InternalName import java.util.concurrent.atomic.AtomicLong @@ -29,9 +28,10 @@ class ByteCodeRepository[BT <: BTypes](val classPath: ClassPath, val btypes: BT) import btypes._ /** - * ClassNodes for classes being compiled in the current compilation run. + * Contains ClassNodes and the canonical path of the source file path of classes being compiled in + * the current compilation run. */ - val compilingClasses: concurrent.Map[InternalName, ClassNode] = recordPerRunCache(concurrent.TrieMap.empty) + val compilingClasses: concurrent.Map[InternalName, (ClassNode, String)] = recordPerRunCache(concurrent.TrieMap.empty) /** * Cache for parsed ClassNodes. @@ -67,20 +67,35 @@ class ByteCodeRepository[BT <: BTypes](val classPath: ClassPath, val btypes: BT) } } - def add(classNode: ClassNode, source: Source) = { - if (source == CompilationUnit) compilingClasses(classNode.name) = classNode - else parsedClasses(classNode.name) = Right((classNode, lruCounter.incrementAndGet())) + def add(classNode: ClassNode, sourceFilePath: Option[String]) = sourceFilePath match { + case Some(path) if path != "" => compilingClasses(classNode.name) = (classNode, path) + case _ => parsedClasses(classNode.name) = Right((classNode, lruCounter.incrementAndGet())) + } + + private def parsedClassNode(internalName: InternalName): Either[ClassNotFound, ClassNode] = { + val r = parsedClasses.get(internalName) match { + case Some(l @ Left(_)) => l + case Some(r @ Right((classNode, _))) => + parsedClasses(internalName) = Right((classNode, lruCounter.incrementAndGet())) + r + case None => + limitCacheSize() + val res = parseClass(internalName).map((_, lruCounter.incrementAndGet())) + parsedClasses(internalName) = res + res + } + r.map(_._1) } /** - * The class node and source for an internal name. If the class node is not yet available, it is - * parsed from the classfile on the compile classpath. + * The class node and source file path (if the class is being compiled) for an internal name. If + * the class node is not yet available, it is parsed from the classfile on the compile classpath. */ - def classNodeAndSource(internalName: InternalName): Either[ClassNotFound, (ClassNode, Source)] = { - classNode(internalName) map (n => { - val source = if (compilingClasses contains internalName) CompilationUnit else Classfile - (n, source) - }) + def classNodeAndSourceFilePath(internalName: InternalName): Either[ClassNotFound, (ClassNode, Option[String])] = { + compilingClasses.get(internalName) match { + case Some((c, p)) => Right((c, Some(p))) + case _ => parsedClassNode(internalName).map((_, None)) + } } /** @@ -88,19 +103,9 @@ class ByteCodeRepository[BT <: BTypes](val classPath: ClassPath, val btypes: BT) * the classfile on the compile classpath. */ def classNode(internalName: InternalName): Either[ClassNotFound, ClassNode] = { - compilingClasses.get(internalName).map(Right(_)) getOrElse { - val r = parsedClasses.get(internalName) match { - case Some(l @ Left(_)) => l - case Some(r @ Right((classNode, _))) => - parsedClasses(internalName) = Right((classNode, lruCounter.incrementAndGet())) - r - case None => - limitCacheSize() - val res = parseClass(internalName).map((_, lruCounter.incrementAndGet())) - parsedClasses(internalName) = res - res - } - r.map(_._1) + compilingClasses.get(internalName) match { + case Some((c, _)) => Right(c) + case None => parsedClassNode(internalName) } } @@ -289,13 +294,3 @@ class ByteCodeRepository[BT <: BTypes](val classPath: ClassPath, val btypes: BT) } } } - -object ByteCodeRepository { - /** - * The source of a ClassNode in the ByteCodeRepository. Can be either [[CompilationUnit]] if the - * class is being compiled or [[Classfile]] if the class was parsed from the compilation classpath. - */ - sealed trait Source - object CompilationUnit extends Source - object Classfile extends Source -} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index d4ff6493a379..40344809bff6 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -16,7 +16,6 @@ import scala.collection.JavaConverters._ import scala.tools.nsc.backend.jvm.BTypes.InternalName import scala.tools.nsc.backend.jvm.BackendReporting._ import scala.tools.nsc.backend.jvm.analysis._ -import ByteCodeRepository.{Source, CompilationUnit} import BytecodeUtils._ class CallGraph[BT <: BTypes](val btypes: BT) { @@ -128,17 +127,17 @@ class CallGraph[BT <: BTypes](val btypes: BT) { methodNode.instructions.iterator.asScala foreach { case call: MethodInsnNode if a.frameAt(call) != null => // skips over unreachable code val callee: Either[OptimizerWarning, Callee] = for { - (method, declarationClass) <- byteCodeRepository.methodNode(call.owner, call.name, call.desc): Either[OptimizerWarning, (MethodNode, InternalName)] - (declarationClassNode, source) <- byteCodeRepository.classNodeAndSource(declarationClass): Either[OptimizerWarning, (ClassNode, Source)] + (method, declarationClass) <- byteCodeRepository.methodNode(call.owner, call.name, call.desc): Either[OptimizerWarning, (MethodNode, InternalName)] + (declarationClassNode, calleeSourceFilePath) <- byteCodeRepository.classNodeAndSourceFilePath(declarationClass): Either[OptimizerWarning, (ClassNode, Option[String])] } yield { val declarationClassBType = classBTypeFromClassNode(declarationClassNode) - val info = analyzeCallsite(method, declarationClassBType, call, source) + val info = analyzeCallsite(method, declarationClassBType, call, calleeSourceFilePath) import info._ Callee( callee = method, calleeDeclarationClass = declarationClassBType, safeToInline = safeToInline, - canInlineFromSource = canInlineFromSource, + sourceFilePath = sourceFilePath, annotatedInline = annotatedInline, annotatedNoInline = annotatedNoInline, samParamTypes = info.samParamTypes, @@ -256,7 +255,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { /** * Just a named tuple used as return type of `analyzeCallsite`. */ - private case class CallsiteInfo(safeToInline: Boolean, canInlineFromSource: Boolean, + private case class CallsiteInfo(safeToInline: Boolean, sourceFilePath: Option[String], annotatedInline: Boolean, annotatedNoInline: Boolean, samParamTypes: IntMap[ClassBType], warning: Option[CalleeInfoWarning]) @@ -264,7 +263,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { /** * Analyze a callsite and gather meta-data that can be used for inlining decisions. */ - private def analyzeCallsite(calleeMethodNode: MethodNode, calleeDeclarationClassBType: ClassBType, call: MethodInsnNode, calleeSource: Source): CallsiteInfo = { + private def analyzeCallsite(calleeMethodNode: MethodNode, calleeDeclarationClassBType: ClassBType, call: MethodInsnNode, calleeSourceFilePath: Option[String]): CallsiteInfo = { val methodSignature = calleeMethodNode.name + calleeMethodNode.desc try { @@ -273,8 +272,6 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // callee, we only check there for the methodInlineInfo, we should find it there. calleeDeclarationClassBType.info.orThrow.inlineInfo.methodInfos.get(methodSignature) match { case Some(methodInlineInfo) => - val canInlineFromSource = compilerSettings.optInlineGlobal || calleeSource == CompilationUnit - val isAbstract = BytecodeUtils.isAbstractMethod(calleeMethodNode) val receiverType = classBTypeFromParsedClassfile(call.owner) @@ -308,13 +305,13 @@ class CallGraph[BT <: BTypes](val btypes: BT) { // static impl method first (safeToRewrite). CallsiteInfo( safeToInline = - canInlineFromSource && + inlinerHeuristics.canInlineFromSource(calleeSourceFilePath) && isStaticallyResolved && // (1) !isAbstract && !BytecodeUtils.isConstructor(calleeMethodNode) && !BytecodeUtils.isNativeMethod(calleeMethodNode) && !BytecodeUtils.hasCallerSensitiveAnnotation(calleeMethodNode), - canInlineFromSource = canInlineFromSource, + sourceFilePath = calleeSourceFilePath, annotatedInline = methodInlineInfo.annotatedInline, annotatedNoInline = methodInlineInfo.annotatedNoInline, samParamTypes = samParamTypes(calleeMethodNode, receiverType), @@ -322,12 +319,12 @@ class CallGraph[BT <: BTypes](val btypes: BT) { case None => val warning = MethodInlineInfoMissing(calleeDeclarationClassBType.internalName, calleeMethodNode.name, calleeMethodNode.desc, calleeDeclarationClassBType.info.orThrow.inlineInfo.warning) - CallsiteInfo(false, false, false, false, IntMap.empty, Some(warning)) + CallsiteInfo(false, None, false, false, IntMap.empty, Some(warning)) } } catch { case Invalid(noInfo: NoClassBTypeInfo) => val warning = MethodInlineInfoError(calleeDeclarationClassBType.internalName, calleeMethodNode.name, calleeMethodNode.desc, noInfo) - CallsiteInfo(false, false, false, false, IntMap.empty, Some(warning)) + CallsiteInfo(false, None, false, false, IntMap.empty, Some(warning)) } } @@ -389,7 +386,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { * gathering the information about this callee. */ final case class Callee(callee: MethodNode, calleeDeclarationClass: btypes.ClassBType, - safeToInline: Boolean, canInlineFromSource: Boolean, + safeToInline: Boolean, sourceFilePath: Option[String], annotatedInline: Boolean, annotatedNoInline: Boolean, samParamTypes: IntMap[btypes.ClassBType], calleeInfoWarning: Option[CalleeInfoWarning]) { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala index 7f9858286eae..081830d61da5 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala @@ -17,7 +17,6 @@ import scala.tools.nsc.backend.jvm.BTypes.InternalName import BytecodeUtils._ import BackendReporting._ import Opcodes._ -import scala.tools.nsc.backend.jvm.opt.ByteCodeRepository.CompilationUnit import scala.collection.JavaConverters._ class ClosureOptimizer[BT <: BTypes](val btypes: BT) { @@ -354,16 +353,15 @@ class ClosureOptimizer[BT <: BTypes](val btypes: BT) { // the method node is needed for building the call graph entry val bodyMethod = byteCodeRepository.methodNode(lambdaBodyHandle.getOwner, lambdaBodyHandle.getName, lambdaBodyHandle.getDesc) - def bodyMethodIsBeingCompiled = byteCodeRepository.classNodeAndSource(lambdaBodyHandle.getOwner).map(_._2 == CompilationUnit).getOrElse(false) + val sourceFilePath = byteCodeRepository.compilingClasses.get(lambdaBodyHandle.getOwner).map(_._2) val callee = bodyMethod.map({ case (bodyMethodNode, bodyMethodDeclClass) => val bodyDeclClassType = classBTypeFromParsedClassfile(bodyMethodDeclClass) - val canInlineFromSource = compilerSettings.optInlineGlobal || bodyMethodIsBeingCompiled Callee( callee = bodyMethodNode, calleeDeclarationClass = bodyDeclClassType, - safeToInline = canInlineFromSource, - canInlineFromSource = canInlineFromSource, + safeToInline = inlinerHeuristics.canInlineFromSource(sourceFilePath), + sourceFilePath = sourceFilePath, annotatedInline = false, annotatedNoInline = false, samParamTypes = callGraph.samParamTypes(bodyMethodNode, bodyDeclClassType), diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala index 17807fb385ed..009742501e9e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala @@ -22,6 +22,8 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { for (pr <- post) assert(pr.callsite.callsiteMethod == callsite.callee.get.callee, s"Callsite method mismatch: main $callsite - post ${pr.callsite}") } + def canInlineFromSource(sourceFilePath: Option[String]) = compilerSettings.optInlineGlobal || sourceFilePath.isDefined + /** * Select callsites from the call graph that should be inlined, grouped by the containing method. * Cyclic inlining requests are allowed, the inliner will eliminate requests to break cycles. @@ -32,14 +34,14 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { // classpath. In order to get only the callsites being compiled, we start at the map of // compilingClasses in the byteCodeRepository. val compilingMethods = for { - classNode <- byteCodeRepository.compilingClasses.valuesIterator - methodNode <- classNode.methods.iterator.asScala + (classNode, _) <- byteCodeRepository.compilingClasses.valuesIterator + methodNode <- classNode.methods.iterator.asScala } yield methodNode compilingMethods.map(methodNode => { var requests = Set.empty[InlineRequest] callGraph.callsites(methodNode).valuesIterator foreach { - case callsite @ Callsite(_, _, _, Right(Callee(callee, calleeDeclClass, safeToInline, canInlineFromSource, calleeAnnotatedInline, _, _, callsiteWarning)), _, _, _, pos, _, _) => + case callsite @ Callsite(_, _, _, Right(Callee(callee, calleeDeclClass, safeToInline, sourceFilePath, calleeAnnotatedInline, _, _, callsiteWarning)), _, _, _, pos, _, _) => inlineRequest(callsite, requests) match { case Some(Right(req)) => requests += req case Some(Left(w)) => @@ -50,7 +52,7 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { } case None => - if (canInlineFromSource && calleeAnnotatedInline && !callsite.annotatedNoInline && bTypes.compilerSettings.optWarningEmitAtInlineFailed) { + if (canInlineFromSource(sourceFilePath) && calleeAnnotatedInline && !callsite.annotatedNoInline && bTypes.compilerSettings.optWarningEmitAtInlineFailed) { // if the callsite is annotated @inline, we report an inline warning even if the underlying // reason is, for example, mixed compilation (which has a separate -opt-warning flag). def initMsg = s"${BackendReporting.methodSignature(calleeDeclClass.internalName, callee)} is annotated @inline but cannot be inlined" diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala index 3cb1fbdae6ff..3e0b889e9c62 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala @@ -19,7 +19,7 @@ class InlinerIllegalAccessTest extends BytecodeTesting { import compiler._ import global.genBCode.bTypes._ - def addToRepo(cls: List[ClassNode]): Unit = for (c <- cls) byteCodeRepository.add(c, ByteCodeRepository.Classfile) + def addToRepo(cls: List[ClassNode]): Unit = for (c <- cls) byteCodeRepository.add(c, None) def assertEmpty(ins: Option[AbstractInsnNode]) = for (i <- ins) throw new AssertionError(textify(i)) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 02cd632af176..4023f1fd3a98 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -43,7 +43,7 @@ class InlinerTest extends BytecodeTesting { // Use the class nodes stored in the byteCodeRepository. The ones returned by compileClasses are not the same, // these are created new from the classfile byte array. They are completely separate instances which cannot // be used to look up methods / callsites in the callGraph hash maps for example. - byteCodeRepository.compilingClasses.valuesIterator.toList.sortBy(_.name) + byteCodeRepository.compilingClasses.valuesIterator.map(_._1).toList.sortBy(_.name) } def checkCallsite(callsite: callGraph.Callsite, callee: MethodNode) = { From 59d6dbc0aac912567d235048b5114cccf965c7ce Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 25 May 2016 15:21:50 +0200 Subject: [PATCH 095/153] clear all flags when resetting a symbol this change is a bit scary because it changes code that's not been changed in 11 years https://github.com/scala/scala/commit/7fa7c93#diff-d5789e5ae5061197d782d08324b260dbL214 --- src/reflect/scala/reflect/internal/Flags.scala | 1 - src/reflect/scala/reflect/internal/Symbols.scala | 2 +- .../tools/nsc/backend/jvm/DirectCompileTest.scala | 11 +++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index 230d30c74ec3..e2522ef280d3 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -235,7 +235,6 @@ class Flags extends ModifierFlags { final val AllFlags = -1L /** These flags can be set when class or module symbol is first created. - * They are the only flags to survive a call to resetFlags(). */ final val TopLevelCreationFlags = MODULE | PACKAGE | FINAL | JAVA diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 6f2d8d802a63..ab52a875f841 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -725,7 +725,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def setFlag(mask: Long): this.type = { _rawflags |= mask ; this } def resetFlag(mask: Long): this.type = { _rawflags &= ~mask ; this } - def resetFlags() { rawflags &= TopLevelCreationFlags } + def resetFlags() { rawflags = 0 } /** Default implementation calls the generic string function, which * will print overloaded flags as . Subclasses diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala index f835e9b14010..36bdb759a6be 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala @@ -88,4 +88,15 @@ class DirectCompileTest extends BytecodeTesting { def compileErroneous(): Unit = { compileToBytes("class C { def f: String = 1 }", allowMessage = _.msg contains "type mismatch") } + + @Test + def residentRedefineFinalFlag(): Unit = { + val compiler = newCompiler() + val a = "final class C { def c1 = 0 }" + // for re-defined class symbols (C), the compiler did not clear the `final` flag. + // so compiling `D` would give an error `illegal inheritance from final class C`. + val b = "class C; class D extends C" + compiler.compileToBytes(a) + compiler.compileToBytes(b) + } } From e1084299350bcc20f5d412993d77b8f956ba3165 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 25 May 2016 15:22:19 +0200 Subject: [PATCH 096/153] SI-9256 check companions in same compilation unit only if same run --- .../scala/tools/nsc/typechecker/Namers.scala | 1 + .../nsc/backend/jvm/DirectCompileTest.scala | 12 ++++++++++ .../backend/jvm/opt/InlineWarningTest.scala | 24 +++++++++---------- .../nsc/backend/jvm/opt/InlinerTest.scala | 10 ++++---- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 2773ee19cff1..9c1ba7ced1d7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -431,6 +431,7 @@ trait Namers extends MethodSynthesis { && !(module isCoDefinedWith clazz) && module.exists && clazz.exists + && (currentRun.compiles(clazz) == currentRun.compiles(module)) ) if (fails) { reporter.error(tree.pos, ( diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala index 36bdb759a6be..a28599cd9212 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala @@ -99,4 +99,16 @@ class DirectCompileTest extends BytecodeTesting { compiler.compileToBytes(a) compiler.compileToBytes(b) } + + @Test + def residentMultipleRunsNotCompanions(): Unit = { + val compiler = newCompiler() + val a = List(("public class A { }", "A.java")) + // when checking that a class and its companion are defined in the same compilation unit, the + // compiler would also emit a warning if the two symbols are defined in separate runs. this + // would lead to an error message when compiling the scala class A. + val b = "class A" + compiler.compileToBytes("", a) + compiler.compileToBytes(b) + } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala index 024cf0c416df..5254d7e1f29f 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala @@ -97,7 +97,7 @@ class InlineWarningTest extends BytecodeTesting { @Test def cannotInlinePrivateCallIntoDifferentClass(): Unit = { val code = - """class M { + """class A { | @inline final def f = { | @noinline def nested = 0 | nested @@ -106,15 +106,15 @@ class InlineWarningTest extends BytecodeTesting { | def t = f // ok |} | - |class N { - | def t(a: M) = a.f // not possible + |class B { + | def t(a: A) = a.f // not possible |} """.stripMargin val warn = - """M::f()I is annotated @inline but could not be inlined: - |The callee M::f()I contains the instruction INVOKESTATIC M.nested$1 ()I - |that would cause an IllegalAccessError when inlined into class N""".stripMargin + """A::f()I is annotated @inline but could not be inlined: + |The callee A::f()I contains the instruction INVOKESTATIC A.nested$1 ()I + |that would cause an IllegalAccessError when inlined into class B""".stripMargin var c = 0 compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn }) @@ -124,7 +124,7 @@ class InlineWarningTest extends BytecodeTesting { @Test def dontWarnWhenNotIlnineAnnotated(): Unit = { val code = - """class M { + """class A { | final def f(t: Int => Int) = { | @noinline def nested = 0 | nested + t(1) @@ -132,16 +132,16 @@ class InlineWarningTest extends BytecodeTesting { | def t = f(x => x + 1) |} | - |class N { - | def t(a: M) = a.f(x => x + 1) + |class B { + | def t(a: A) = a.f(x => x + 1) |} """.stripMargin compileToBytes(code, allowMessage = _ => false) // no warnings allowed val warn = - """M::f(Lscala/Function1;)I could not be inlined: - |The callee M::f(Lscala/Function1;)I contains the instruction INVOKESTATIC M.nested$1 ()I - |that would cause an IllegalAccessError when inlined into class N""".stripMargin + """A::f(Lscala/Function1;)I could not be inlined: + |The callee A::f(Lscala/Function1;)I contains the instruction INVOKESTATIC A.nested$1 ()I + |that would cause an IllegalAccessError when inlined into class B""".stripMargin var c = 0 compilerWarnAll.compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn }) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 4023f1fd3a98..9b538573dce4 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -835,11 +835,11 @@ class InlinerTest extends BytecodeTesting { @Test def inlineInvokeSpecial(): Unit = { val code = - """class Aa { + """class A { | def f1 = 0 |} - |class B extends Aa { - | @inline final override def f1 = 1 + super.f1 // invokespecial Aa.f1 + |class B extends A { + | @inline final override def f1 = 1 + super.f1 // invokespecial A.f1 | | private def f2m = 0 // public B$$f2m in bytecode | @inline final def f2 = f2m // invokevirtual B.B$$f2m @@ -863,13 +863,13 @@ class InlinerTest extends BytecodeTesting { val warn = """B::f1()I is annotated @inline but could not be inlined: - |The callee B::f1()I contains the instruction INVOKESPECIAL Aa.f1 ()I + |The callee B::f1()I contains the instruction INVOKESPECIAL A.f1 ()I |that would cause an IllegalAccessError when inlined into class T.""".stripMargin var c = 0 val List(a, b, t) = compile(code, allowMessage = i => {c += 1; i.msg contains warn}) assert(c == 1, c) - assertInvoke(getMethod(b, "t1"), "Aa", "f1") + assertInvoke(getMethod(b, "t1"), "A", "f1") assertInvoke(getMethod(b, "t2"), "B", "B$$f2m") assertInvoke(getMethod(b, "t3"), "B", "") assertInvoke(getMethod(b, "t4"), "B", "") From 2980c3921f1270f05add25239da93e05f64ad45f Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 31 May 2016 09:45:10 +0200 Subject: [PATCH 097/153] Keep line numbers when inlining from the same compilation unit So far, line numbers were kept only when inlining from the same class. We can also keep them when inlining from a different class defined in the same compilation unit. Longer-term we should support JSR-45, see SI-7518 and scala-dev#3. --- .../tools/nsc/backend/jvm/opt/Inliner.scala | 11 ++++- .../nsc/backend/jvm/opt/InlinerTest.scala | 48 +++++++++++++++++++ .../scala/tools/testing/BytecodeTesting.scala | 2 +- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index d18963ec8bbd..7b4cfe2a18d2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -253,7 +253,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { def inlineCallsite(callsite: Callsite): Unit = { import callsite.{callsiteClass, callsiteMethod, callsiteInstruction, receiverKnownNotNull, callsiteStackHeight} val Right(callsiteCallee) = callsite.callee - import callsiteCallee.{callee, calleeDeclarationClass} + import callsiteCallee.{callee, calleeDeclarationClass, sourceFilePath} // Inlining requires the callee not to have unreachable code, the analyzer used below should not // return any `null` frames. Note that inlining a method can create unreachable code. Example: @@ -268,7 +268,14 @@ class Inliner[BT <: BTypes](val btypes: BT) { // New labels for the cloned instructions val labelsMap = cloneLabels(callee) - val (clonedInstructions, instructionMap, hasSerializableClosureInstantiation) = cloneInstructions(callee, labelsMap, keepLineNumbers = callsiteClass == calleeDeclarationClass) + val sameSourceFile = sourceFilePath match { + case Some(calleeSource) => byteCodeRepository.compilingClasses.get(callsiteClass.internalName) match { + case Some((_, `calleeSource`)) => true + case _ => false + } + case _ => false + } + val (clonedInstructions, instructionMap, hasSerializableClosureInstantiation) = cloneInstructions(callee, labelsMap, keepLineNumbers = sameSourceFile) // local vars in the callee are shifted by the number of locals at the callsite val localVarShift = callsiteMethod.maxLocals diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 9b538573dce4..9173a1d1893e 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -1526,4 +1526,52 @@ class InlinerTest extends BytecodeTesting { val c :: _ = compileClassesSeparately(codes, extraArgs = compilerArgs) assertInvoke(getMethod(c, "t"), "p1/Implicits$RichFunction1$", "toRx$extension") } + + @Test + def keepLineNumbersPerCompilationUnit(): Unit = { + val code1 = + """class A { + | def fx(): Unit = () + | @inline final def ma = { + | fx() + | 1 + | } + |} + """.stripMargin + val code2 = + """class B extends A { + | @inline final def mb = { + | fx() + | 1 + | } + |} + |class C extends B { + | @inline final def mc = { + | fx() + | 1 + | } + | def t1 = ma // no lines, not the same source file + | def t2 = mb // lines + | def t3 = mc // lines + |} + """.stripMargin + notPerRun.foreach(_.clear()) + val run = compiler.newRun + run.compileSources(List(makeSourceFile(code1, "A.scala"), makeSourceFile(code2, "B.scala"))) + val List(_, _, c) = readAsmClasses(getGeneratedClassfiles(global.settings.outputDirs.getSingleOutput.get)) + def is(name: String) = getMethod(c, name).instructions.filterNot(_.isInstanceOf[FrameEntry]) + + assertSameCode(is("t1"), List( + Label(0), LineNumber(12, Label(0)), + VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "A", "fx", "()V", false), + Op(ICONST_1), Op(IRETURN), Label(6))) + + assertSameCode(is("t2"), List( + Label(0), LineNumber(3, Label(0)), VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "B", "fx", "()V", false), + Label(4), LineNumber(4, Label(4)), Op(ICONST_1), Op(IRETURN), Label(8))) + + assertSameCode(is("t3"), List( + Label(0), LineNumber(9, Label(0)), VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "C", "fx", "()V", false), + Label(4), LineNumber(10, Label(4)), Op(ICONST_1), Op(IRETURN), Label(8))) + } } diff --git a/test/junit/scala/tools/testing/BytecodeTesting.scala b/test/junit/scala/tools/testing/BytecodeTesting.scala index 1a0c1e210a48..4ddb6580df9e 100644 --- a/test/junit/scala/tools/testing/BytecodeTesting.scala +++ b/test/junit/scala/tools/testing/BytecodeTesting.scala @@ -29,7 +29,7 @@ class Compiler(val global: Global) { global.settings.outputDirs.setSingleOutput(new VirtualDirectory("(memory)", None)) } - private def newRun: global.Run = { + def newRun: global.Run = { global.reporter.reset() resetOutput() new global.Run() From a1ea0aa0a6136c13baa41268d7dbd4197924d3c9 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 6 Jun 2016 10:50:09 +0200 Subject: [PATCH 098/153] Remove TopLevelCreationFlags --- src/reflect/scala/reflect/internal/Flags.scala | 9 ++------- src/reflect/scala/reflect/internal/Mirrors.scala | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index e2522ef280d3..e06decea6d25 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -234,13 +234,8 @@ class Flags extends ModifierFlags { */ final val AllFlags = -1L - /** These flags can be set when class or module symbol is first created. - */ - final val TopLevelCreationFlags = - MODULE | PACKAGE | FINAL | JAVA - // TODO - there's no call to slap four flags onto every package. - final val PackageFlags = TopLevelCreationFlags + final val PackageFlags = MODULE | PACKAGE | FINAL | JAVA // FINAL not included here due to possibility of object overriding. // In fact, FINAL should not be attached regardless. We should be able @@ -300,7 +295,7 @@ class Flags extends ModifierFlags { final val ConstrFlags = JAVA /** Module flags inherited by their module-class */ - final val ModuleToClassFlags = AccessFlags | TopLevelCreationFlags | CASE | SYNTHETIC + final val ModuleToClassFlags = AccessFlags | PackageFlags | CASE | SYNTHETIC /** These flags are not pickled */ final val FlagsNotPickled = IS_ERROR | OVERLOADED | LIFTED | TRANS_FLAG | LOCKED | TRIEDCOOKING diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala index 756300d4036f..3d1c160d5299 100644 --- a/src/reflect/scala/reflect/internal/Mirrors.scala +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -273,7 +273,7 @@ trait Mirrors extends api.Mirrors { // is very beneficial for a handful of bootstrap symbols to have // first class identities sealed trait WellKnownSymbol extends Symbol { - this initFlags (TopLevelCreationFlags | STATIC) + this initFlags (PackageFlags | STATIC) } // Features common to RootClass and RootPackage, the roots of all // type and term symbols respectively. From 3f3a3bb57499fb919e798d03bbc4e84ede8e55d6 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 7 Jun 2016 00:38:01 -0700 Subject: [PATCH 099/153] SI-9245 Fresher name in Try and test Fresh name for catcher gets a dollar. "Here, have a dollar." Test due to retronym demonstrates possible conflict. Over the lifetime of the universe, surely at least one code monkey would type in that identifier to catch a banana. --- .../tools/nsc/ast/parser/TreeBuilder.scala | 2 +- test/files/pos/t9245.scala | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t9245.scala diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index cc9e39f43045..45f731686a44 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -105,7 +105,7 @@ abstract class TreeBuilder { def makeCatchFromExpr(catchExpr: Tree): CaseDef = { val binder = freshTermName() val pat = Bind(binder, Typed(Ident(nme.WILDCARD), Ident(tpnme.Throwable))) - val catchDef = ValDef(Modifiers(ARTIFACT), freshTermName("catchExpr"), TypeTree(), catchExpr) + val catchDef = ValDef(Modifiers(ARTIFACT), freshTermName("catchExpr$"), TypeTree(), catchExpr) val catchFn = Ident(catchDef.name) val body = atPos(catchExpr.pos.makeTransparent)(Block( List(catchDef), diff --git a/test/files/pos/t9245.scala b/test/files/pos/t9245.scala new file mode 100644 index 000000000000..87bc1fa0ef84 --- /dev/null +++ b/test/files/pos/t9245.scala @@ -0,0 +1,27 @@ + +/* +Was: +test/files/pos/t9245.scala:5: error: recursive value catchExpr1 needs type + try {} catch catchExpr1 + ^ + +Now: + def catchExpr1: PartialFunction[Throwable,Any] = scala.this.Predef.???; + def test: Any = try { + () + } catch { + case (x$1 @ (_: Throwable)) => { + val catchExpr$1: PartialFunction[Throwable,Any] = Test.this.catchExpr1; + if (catchExpr$1.isDefinedAt(x$1)) + catchExpr$1.apply(x$1) + else + throw x$1 + } + } +*/ +trait Test { + def catchExpr1: PartialFunction[Throwable, Any] = ??? + def test = { + try {} catch catchExpr1 + } +} From c7e2b2878d0128a1e74888dca98219182df78aa4 Mon Sep 17 00:00:00 2001 From: af Date: Fri, 10 Jun 2016 14:07:17 +0300 Subject: [PATCH 100/153] Typo fix --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index da86f6274b79..13bbd8be033d 100644 --- a/build.sbt +++ b/build.sbt @@ -69,7 +69,7 @@ val scalaSwingDep = withoutScalaLang("org.scala-lang.modules" %% "scala-swing" % val scalaXmlDep = withoutScalaLang("org.scala-lang.modules" %% "scala-xml" % versionNumber("scala-xml")) val partestDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest" % versionNumber("partest")) val junitDep = "junit" % "junit" % "4.11" -val junitIntefaceDep = "com.novocode" % "junit-interface" % "0.11" % "test" +val junitInterfaceDep = "com.novocode" % "junit-interface" % "0.11" % "test" val asmDep = "org.scala-lang.modules" % "scala-asm" % versionProps("scala-asm.version") val jlineDep = "jline" % "jline" % versionProps("jline.version") val antDep = "org.apache.ant" % "ant" % "1.9.4" @@ -576,7 +576,7 @@ lazy val junit = project.in(file("test") / "junit") .settings(disablePublishing: _*) .settings( fork in Test := true, - libraryDependencies ++= Seq(junitDep, junitIntefaceDep), + libraryDependencies ++= Seq(junitDep, junitInterfaceDep), testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"), unmanagedSourceDirectories in Test := List(baseDirectory.value) ) From 956fee80ae15a0b0eebfb52bdd18f4df9511c479 Mon Sep 17 00:00:00 2001 From: Raul Bache Date: Sun, 12 Jun 2016 21:15:50 +0200 Subject: [PATCH 101/153] If Range is sealed, it makes sense to have Range.Inclusive final. --- src/library/scala/collection/immutable/Range.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 2e567501155f..82203b3d1a53 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -437,7 +437,7 @@ object Range { def count(start: Int, end: Int, step: Int): Int = count(start, end, step, isInclusive = false) - class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) { + final class Inclusive(start: Int, end: Int, step: Int) extends Range(start, end, step) { // override def par = new ParRange(this) override def isInclusive = true override protected def copy(start: Int, end: Int, step: Int): Range = new Inclusive(start, end, step) From f2d0f1e85d8b348cd2506a45502e4e59f9ec8e49 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Tue, 14 Jun 2016 12:38:58 +0200 Subject: [PATCH 102/153] Use sbt for PR validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Support directories in `-doc-external-doc`: It is documented as accepting a “classpath_entry_path” for the keys but this only worked for JARs and not for individual class files. When checking for external-doc mappings for a Symbol, we now find the root directory relative to a class file instead of using the full class file path. The corresponding tests for SI-191 and SI8557 are also fixed to support individual class files instead of JARs in partest. This is required for the sbt build which runs partest on “quick” instead of “pack”. - Fix version and repository handling for bootstrapping. The bootstrap `scalaInstance` can now be resolved from any repository added to the project (not just the bootstrap repositories) by using a different workaround for https://github.com/sbt/sbt/issues/1872. - Workaround for https://github.com/sbt/sbt/issues/2640 (putting the wrong `scalaInstance` on partest’s classpath). The required `ScalaInstance` constructor is deprecated, so we have to disable deprecation warnings and fatal warnings until there is a better fix. - Add MiMa to the sbt build (port of the old `test.bc` ant task). The sbt-mima plugin doesn’t have all the features we need, so we do it manually in a similar way to what the plugin does. Checks are done in both directions for the `library` and `compiler` projects. The base version has to be set in `build.sbt`. When set to `None`, MiMa checks are skipped. MiMa checks are run sequentially to avoid spurious errors (see https://github.com/typesafehub/migration-manager/issues/115). - Port the OSGi tests to the sbt build. The set of JARs that gets copied into build/osgi as bundles is a bit different from the ant build. We omit the source JARs but add additional modules that are part of the Scala distribution, which seems more correct. - Get rid up `pull-binary-libs.sh` for the sbt build. Add artifacts are resolved from the special bootstrap repository through Ivy. The special `code.jar` and `instrumented.jar` artifacts are copied to the location where partest expects them (because these paths are hardcoded in partest). Other extra JARs for partest in `test/files/lib` are referenced directly from the Ivy cache. - Move common settings that should be available with unqualified names in local `.sbt` files and on the command line into an auto-plugin. - Add an `antStyle` setting to sbt to allow users to easily enable ant-style incremental compilation instead of sbt’s standard name hashing with `set antStyle := true`. - Disable verbose `info`-level logging during sbt startup for both, `validate/test` and `validate/publish-core` jobs. Update logging is no longer disabled when running locally (where it is useful and doesn’t generate excessive output). - Pass optimization flags for scalac down to partest, using the new partest version 1.0.15\6. - Call the new sbt-based PR validation from `scripts/jobs/validate/test`. - Disable the tests `run/t7843-jsr223-service` and `run/t7933` from https://github.com/scala/scala/pull/4959 for now. We need to set up a new test project (either partest or junit) that can run them on a packaged version of Scala, or possibly move them into a separate project that would naturally run from a packaged Scala as part of the community build. --- build.sbt | 187 ++++++++++++------ project/BuildSettings.scala | 11 ++ project/MiMa.scala | 95 +++++++++ project/Osgi.scala | 4 +- project/Quiet.scala | 2 - project/ScalaTool.scala | 12 +- project/ScriptCommands.scala | 21 +- project/VersionUtil.scala | 34 +++- project/plugins.sbt | 5 + scripts/jobs/validate/publish-core | 4 +- scripts/jobs/validate/test | 35 +++- .../tools/nsc/doc/model/MemberLookup.scala | 18 +- .../run/t7843-jsr223-service.check | 0 .../run/t7843-jsr223-service.scala | 0 test/{files => disabled}/run/t7933.check | 0 test/{files => disabled}/run/t7933.scala | 0 test/osgi/src/logback.xml | 10 + test/scaladoc/.gitignore | 2 + test/scaladoc/run/SI-191.scala | 12 +- test/scaladoc/run/t8557.scala | 20 +- versions.properties | 2 +- 21 files changed, 382 insertions(+), 92 deletions(-) create mode 100644 project/BuildSettings.scala create mode 100644 project/MiMa.scala rename test/{files => disabled}/run/t7843-jsr223-service.check (100%) rename test/{files => disabled}/run/t7843-jsr223-service.scala (100%) rename test/{files => disabled}/run/t7933.check (100%) rename test/{files => disabled}/run/t7933.scala (100%) create mode 100644 test/osgi/src/logback.xml create mode 100644 test/scaladoc/.gitignore diff --git a/build.sbt b/build.sbt index 13bbd8be033d..3df0d43c0009 100644 --- a/build.sbt +++ b/build.sbt @@ -55,25 +55,23 @@ import VersionUtil._ -val bootstrapScalaVersion = versionProps("starr.version") - -def withoutScalaLang(moduleId: ModuleID): ModuleID = moduleId exclude("org.scala-lang", "*") - -// exclusion of the scala-library transitive dependency avoids eviction warnings during `update`. -val actorsMigrationDep = withoutScalaLang("org.scala-lang" %% "scala-actors-migration" % versionNumber("actors-migration")) -val akkaActorDep = withoutScalaLang("com.typesafe.akka" %% "akka-actor" % versionNumber("akka-actor")) -val scalaContinuationsLibraryDep = withoutScalaLang("org.scala-lang.plugins" %% "scala-continuations-library" % versionNumber("scala-continuations-library")) -val scalaContinuationsPluginDep = withoutScalaLang("org.scala-lang.plugins" % ("scala-continuations-plugin_" + versionProps("scala.full.version")) % versionNumber("scala-continuations-plugin")) -val scalaParserCombinatorsDep = withoutScalaLang("org.scala-lang.modules" %% "scala-parser-combinators" % versionNumber("scala-parser-combinators")) -val scalaSwingDep = withoutScalaLang("org.scala-lang.modules" %% "scala-swing" % versionNumber("scala-swing")) -val scalaXmlDep = withoutScalaLang("org.scala-lang.modules" %% "scala-xml" % versionNumber("scala-xml")) -val partestDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest" % versionNumber("partest")) -val junitDep = "junit" % "junit" % "4.11" -val junitInterfaceDep = "com.novocode" % "junit-interface" % "0.11" % "test" -val asmDep = "org.scala-lang.modules" % "scala-asm" % versionProps("scala-asm.version") -val jlineDep = "jline" % "jline" % versionProps("jline.version") -val antDep = "org.apache.ant" % "ant" % "1.9.4" -val scalacheckDep = withoutScalaLang("org.scalacheck" %% "scalacheck" % versionNumber("scalacheck") % "it") +// Scala dependencies: +val scalaContinuationsPluginDep = scalaDep("org.scala-lang.plugins", "scala-continuations-plugin", compatibility = "full") +val scalaContinuationsLibraryDep = scalaDep("org.scala-lang.plugins", "scala-continuations-library") +val scalaParserCombinatorsDep = scalaDep("org.scala-lang.modules", "scala-parser-combinators") +val scalaSwingDep = scalaDep("org.scala-lang.modules", "scala-swing") +val scalaXmlDep = scalaDep("org.scala-lang.modules", "scala-xml") +val partestDep = scalaDep("org.scala-lang.modules", "scala-partest", versionProp = "partest") +val akkaActorDep = scalaDep("com.typesafe.akka", "akka-actor") +val actorsMigrationDep = scalaDep("org.scala-lang", "scala-actors-migration", versionProp = "actors-migration") +val scalacheckDep = scalaDep("org.scalacheck", "scalacheck", scope = "it") + +// Non-Scala dependencies: +val junitDep = "junit" % "junit" % "4.11" +val junitInterfaceDep = "com.novocode" % "junit-interface" % "0.11" % "test" +val asmDep = "org.scala-lang.modules" % "scala-asm" % versionProps("scala-asm.version") +val jlineDep = "jline" % "jline" % versionProps("jline.version") +val antDep = "org.apache.ant" % "ant" % "1.9.4" /** Publish to ./dists/maven-sbt, similar to the ANT build which publishes to ./dists/maven. This * can be used to compare the output of the sbt and ANT builds during the transition period. Any @@ -117,20 +115,27 @@ lazy val publishSettings : Seq[Setting[_]] = Seq( globalVersionSettings baseVersion in Global := "2.11.9" baseVersionSuffix in Global := "SNAPSHOT" +mimaReferenceVersion in Global := Some("2.11.0") lazy val commonSettings = clearSourceAndResourceDirectories ++ publishSettings ++ Seq[Setting[_]]( organization := "org.scala-lang", - scalaVersion := bootstrapScalaVersion, // we don't cross build Scala itself crossPaths := false, // do not add Scala library jar as a dependency automatically autoScalaLibrary := false, - // we also do not add scala instance automatically because it introduces - // a circular instance, see: https://github.com/sbt/sbt/issues/1872 + // Avoid circular dependencies for scalaInstance (see https://github.com/sbt/sbt/issues/1872) managedScalaInstance := false, - // this is a way to workaround issue described in https://github.com/sbt/sbt/issues/1872 - // check it out for more details - scalaInstance := ScalaInstance(scalaVersion.value, appConfiguration.value.provider.scalaProvider.launcher getScala scalaVersion.value), + scalaInstance := { + val s = (scalaInstance in bootstrap).value + // sbt claims that s.isManagedVersion is false even though s was resolved by Ivy + // We create a managed copy to prevent sbt from putting it on the classpath where we don't want it + if(s.isManagedVersion) s else { + val s2 = new ScalaInstance(s.version, s.loader, s.libraryJar, s.compilerJar, s.extraJars, Some(s.actualVersion)) + assert(s2.isManagedVersion) + s2 + } + }, + scalaVersion := (scalaVersion in bootstrap).value, // we always assume that Java classes are standalone and do not have any dependency // on Scala classes compileOrder := CompileOrder.JavaThenScala, @@ -151,7 +156,7 @@ lazy val commonSettings = clearSourceAndResourceDirectories ++ publishSettings + target := (baseDirectory in ThisBuild).value / "target" / thisProject.value.id, classDirectory in Compile := buildDirectory.value / "quick/classes" / thisProject.value.id, target in Compile in doc := buildDirectory.value / "scaladoc" / thisProject.value.id, - // given that classDirectory and doc target are overriden to be _outside_ of target directory, we have + // given that classDirectory and doc target are overridden to be _outside_ of target directory, we have // to make sure they are being cleaned properly cleanFiles += (classDirectory in Compile).value, cleanFiles += (target in Compile in doc).value, @@ -166,9 +171,10 @@ lazy val commonSettings = clearSourceAndResourceDirectories ++ publishSettings + "-sourcepath", (baseDirectory in ThisBuild).value.toString, "-doc-source-url", s"https://github.com/scala/scala/tree/${versionProperties.value.githubTree}€{FILE_PATH}.scala#L1" ), + incOptions <<= (incOptions in LocalProject("root")), homepage := Some(url("http://www.scala-lang.org")), startYear := Some(2002), - licenses += ("BSD 3-Clause", url("http://www.scala-lang.org/license.html")), + licenses += (("BSD 3-Clause", url("http://www.scala-lang.org/license.html"))), apiURL := Some(url("http://www.scala-lang.org/api/" + versionProperties.value.mavenVersion + "/")), pomIncludeRepository := { _ => false }, pomExtra := { @@ -213,8 +219,7 @@ lazy val commonSettings = clearSourceAndResourceDirectories ++ publishSettings + // Don't log process output (e.g. of forked `compiler/runMain ...Main`), just pass it // directly to stdout outputStrategy in run := Some(StdoutOutput), - Quiet.silenceScalaBinaryVersionWarning, - Quiet.silenceIvyUpdateInfoLogging + Quiet.silenceScalaBinaryVersionWarning ) /** Extra post-processing for the published POM files. These are needed to create POMs that @@ -250,7 +255,7 @@ def removePomDependencies(deps: (String, String)*): Seq[Setting[_]] = Seq( val n2 = pomPostProcess.value.apply(n) import scala.xml._ import scala.xml.transform._ - (new RuleTransformer(new RewriteRule { + new RuleTransformer(new RewriteRule { override def transform(node: Node) = node match { case e: Elem if e.label == "dependency" && deps.exists { case (g, a) => @@ -259,13 +264,13 @@ def removePomDependencies(deps: (String, String)*): Seq[Setting[_]] = Seq( } => Seq.empty case n => Seq(n) } - })).transform(Seq(n2)).head + }).transform(Seq(n2)).head }, deliverLocal := { import scala.xml._ import scala.xml.transform._ val f = deliverLocal.value - val e = (new RuleTransformer(new RewriteRule { + val e = new RuleTransformer(new RewriteRule { override def transform(node: Node) = node match { case e: Elem if e.label == "dependency" && { val org = e.attribute("org").getOrElse("").toString @@ -276,7 +281,7 @@ def removePomDependencies(deps: (String, String)*): Seq[Setting[_]] = Seq( } => Seq.empty case n => Seq(n) } - })).transform(Seq(XML.loadFile(f))).head + }).transform(Seq(XML.loadFile(f))).head XML.save(f.getAbsolutePath, e, xmlDecl = true) f } @@ -309,7 +314,7 @@ lazy val setJarLocation: Setting[_] = lazy val scalaSubprojectSettings: Seq[Setting[_]] = commonSettings :+ setJarLocation def filterDocSources(ff: FileFilter): Seq[Setting[_]] = Seq( - sources in (Compile, doc) ~= (_.filter(ff.accept _)), + sources in (Compile, doc) ~= (_.filter(ff.accept)), // Excluded sources may still be referenced by the included sources, so we add the compiler // output to the scaladoc classpath to resolve them. For the `library` project this is // always required because otherwise the compiler cannot even initialize Definitions without @@ -326,6 +331,11 @@ def regexFileFilter(s: String): FileFilter = new FileFilter { def accept(f: File) = pat.matcher(f.getAbsolutePath.replace('\\', '/')).matches() } +// This project provides the STARR scalaInstance for bootstrapping +lazy val bootstrap = (project in file("target/bootstrap")).settings( + scalaVersion := versionProps("starr.version") +) + lazy val library = configureAsSubproject(project) .settings(generatePropertiesFileSettings: _*) .settings(Osgi.settings: _*) @@ -363,6 +373,7 @@ lazy val library = configureAsSubproject(project) .settings(filterDocSources("*.scala" -- (regexFileFilter(".*/runtime/.*\\$\\.scala") || regexFileFilter(".*/runtime/ScalaRunTime\\.scala") || regexFileFilter(".*/runtime/StringAdd\\.scala"))): _*) + .settings(MiMa.settings: _*) .dependsOn(forkjoin) lazy val reflect = configureAsSubproject(project) @@ -385,6 +396,7 @@ lazy val reflect = configureAsSubproject(project) "/project/packaging" -> jar ) ) + .settings(MiMa.settings: _*) .dependsOn(library) lazy val compiler = configureAsSubproject(project) @@ -581,6 +593,56 @@ lazy val junit = project.in(file("test") / "junit") unmanagedSourceDirectories in Test := List(baseDirectory.value) ) +lazy val osgiTestFelix = osgiTestProject( + project.in(file(".") / "target" / "osgiTestFelix"), + "org.apache.felix" % "org.apache.felix.framework" % "4.4.0") + +lazy val osgiTestEclipse = osgiTestProject( + project.in(file(".") / "target" / "osgiTestEclipse"), + "org.eclipse.osgi" % "org.eclipse.osgi" % "3.7.1") + +def osgiTestProject(p: Project, framework: ModuleID) = p + .dependsOn(library, reflect, compiler, actors, forkjoin) + .settings(clearSourceAndResourceDirectories: _*) + .settings(commonSettings: _*) + .settings(disableDocs: _*) + .settings(disablePublishing: _*) + .settings( + fork in Test := true, + parallelExecution in Test := false, + libraryDependencies ++= { + val paxExamVersion = "3.5.0" // Last version which supports Java 6 + Seq( + junitDep, + junitInterfaceDep, + "org.ops4j.pax.exam" % "pax-exam-container-native" % paxExamVersion + exclude("org.osgi", "org.osgi.core"), // Avoid dragging in a dependency which requires Java >6 + "org.osgi" % "org.osgi.core" % "4.2.0" % "provided", // The framework (Felix / Eclipse) provides the classes + "org.ops4j.pax.exam" % "pax-exam-junit4" % paxExamVersion, + "org.ops4j.pax.exam" % "pax-exam-link-assembly" % paxExamVersion, + "org.ops4j.pax.url" % "pax-url-aether" % "2.2.0", + "org.ops4j.pax.swissbox" % "pax-swissbox-tracker" % "1.8.0", + "ch.qos.logback" % "logback-core" % "1.1.2", + "ch.qos.logback" % "logback-classic" % "1.1.2", + framework % "test" + ) + }, + Keys.test in Test <<= Keys.test in Test dependsOn (packageBin in Compile), + testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v", "-q"), + unmanagedSourceDirectories in Test := List((baseDirectory in ThisBuild).value / "test" / "osgi" / "src"), + unmanagedResourceDirectories in Compile := (unmanagedSourceDirectories in Test).value, + includeFilter in unmanagedResources in Compile := "*.xml", + packageBin in Compile := { // Put the bundle JARs required for the tests into build/osgi + val targetDir = (buildDirectory in ThisBuild).value / "osgi" + val mappings = ((mkPack in dist).value / "lib").listFiles.collect { + case f if f.getName.startsWith("scala-") && f.getName.endsWith(".jar") => (f, targetDir / f.getName) + } + IO.copy(mappings, overwrite = true) + targetDir + }, + cleanFiles += (buildDirectory in ThisBuild).value / "osgi" + ) + lazy val partestJavaAgent = Project("partest-javaagent", file(".") / "src" / "partest-javaagent") .settings(commonSettings: _*) .settings(generatePropertiesFileSettings: _*) @@ -610,8 +672,15 @@ lazy val test = project .settings(Defaults.itSettings: _*) .settings( libraryDependencies ++= Seq(asmDep, partestDep, scalaXmlDep, scalacheckDep), - unmanagedBase in IntegrationTest := baseDirectory.value / "files" / "lib", - unmanagedJars in IntegrationTest <+= (unmanagedBase) (j => Attributed.blank(j)) map(identity), + libraryDependencies ++= { + // Resolve the JARs for all test/files/lib/*.jar.desired.sha1 files through Ivy + val baseDir = (baseDirectory in ThisBuild).value + (baseDir / "test/files/lib").list.toSeq.filter(_.endsWith(".jar.desired.sha1")) + .map(f => bootstrapDep(baseDir, "test/files/lib", f.dropRight(17))) + }, + // Two hardcoded depenencies in partest, resolved in the otherwise unused scope "test": + libraryDependencies += bootstrapDep((baseDirectory in ThisBuild).value, "test/files/codelib", "code") % "test", + libraryDependencies += bootstrapDep((baseDirectory in ThisBuild).value, "test/files/speclib", "instrumented") % "test", // no main sources sources in Compile := Seq.empty, // test sources are compiled in partest run, not here @@ -619,18 +688,24 @@ lazy val test = project fork in IntegrationTest := true, javaOptions in IntegrationTest += "-Xmx1G", testFrameworks += new TestFramework("scala.tools.partest.sbt.Framework"), - testOptions in IntegrationTest += Tests.Setup( () => root.base.getAbsolutePath + "/pull-binary-libs.sh" ! ), testOptions in IntegrationTest += Tests.Argument("-Dpartest.java_opts=-Xmx1024M -Xms64M -XX:MaxPermSize=128M"), - definedTests in IntegrationTest += ( - new sbt.TestDefinition( - "partest", - // marker fingerprint since there are no test classes - // to be discovered by sbt: - new sbt.testing.AnnotatedFingerprint { - def isModule = true - def annotationName = "partest" - }, true, Array()) - ) + testOptions in IntegrationTest += Tests.Argument("-Dpartest.scalac_opts=" + (scalacOptions in Compile).value.mkString(" ")), + testOptions in IntegrationTest += Tests.Setup { () => + val cp = (dependencyClasspath in Test).value + val baseDir = (baseDirectory in ThisBuild).value + // Copy code.jar and instrumented.jar to the location where partest expects them + copyBootstrapJar(cp, baseDir, "test/files/codelib", "code") + copyBootstrapJar(cp, baseDir, "test/files/speclib", "instrumented") + }, + definedTests in IntegrationTest += new sbt.TestDefinition( + "partest", + // marker fingerprint since there are no test classes + // to be discovered by sbt: + new sbt.testing.AnnotatedFingerprint { + def isModule = true + def annotationName = "partest" + }, true, Array() + ) ) lazy val manual = configureAsSubproject(project) @@ -704,7 +779,7 @@ lazy val scalaDist = Project("scala-dist", file(".") / "target" / "scala-dist-di ) .dependsOn(libraryAll, compiler, scalap) -lazy val root = (project in file(".")) +lazy val root: Project = (project in file(".")) .settings(disableDocs: _*) .settings(disablePublishing: _*) .settings(generateBuildCharacterFileSettings: _*) @@ -712,8 +787,9 @@ lazy val root = (project in file(".")) publish := {}, publishLocal := {}, commands ++= ScriptCommands.all, - Quiet.silenceIvyUpdateInfoLogging -) + antStyle := false, + incOptions := incOptions.value.withNameHashing(!antStyle.value).withAntStyle(antStyle.value) + ) .aggregate(library, forkjoin, reflect, compiler, interactive, repl, replJline, replJlineEmbedded, scaladoc, scalap, actors, partestExtras, junit, libraryAll, scalaDist).settings( sources in Compile := Seq.empty, @@ -737,8 +813,9 @@ lazy val dist = (project in file("dist")) val props = new java.util.Properties() props.setProperty("partest.classpath", cp.map(_.data.getAbsolutePath).mkString(sys.props("path.separator"))) IO.write(props, null, propsFile) + (buildDirectory in ThisBuild).value / "quick" } dependsOn ((distDependencies.map(products in Runtime in _) :+ mkBin): _*), - mkPack <<= Def.task {} dependsOn (packagedArtifact in (Compile, packageBin), mkBin), + mkPack <<= Def.task { (buildDirectory in ThisBuild).value / "pack" } dependsOn (packagedArtifact in (Compile, packageBin), mkBin), target := (baseDirectory in ThisBuild).value / "target" / thisProject.value.id, packageBin in Compile := { val extraDeps = Set(scalaContinuationsLibraryDep, scalaContinuationsPluginDep, scalaSwingDep, scalaParserCombinatorsDep, scalaXmlDep) @@ -749,7 +826,7 @@ lazy val dist = (project in file("dist")) case (Some(m), f) if extraModules contains uniqueModule(m) => f } val jlineJAR = (dependencyClasspath in Compile).value.find(_.get(moduleID.key) == Some(jlineDep)).get.data - val mappings = extraJars.map(f => (f, targetDir / f.getName)) :+ (jlineJAR, targetDir / "jline.jar") + val mappings = extraJars.map(f => (f, targetDir / f.getName)) :+ ((jlineJAR, targetDir / "jline.jar")) IO.copy(mappings, overwrite = true) targetDir }, @@ -802,8 +879,8 @@ def configureAsForkOfJavaProject(project: Project): Project = { lazy val buildDirectory = settingKey[File]("The directory where all build products go. By default ./build") lazy val mkBin = taskKey[Seq[File]]("Generate shell script (bash or Windows batch).") -lazy val mkQuick = taskKey[Unit]("Generate a full build, including scripts, in build/quick") -lazy val mkPack = taskKey[Unit]("Generate a full build, including scripts, in build/pack") +lazy val mkQuick = taskKey[File]("Generate a full build, including scripts, in build/quick") +lazy val mkPack = taskKey[File]("Generate a full build, including scripts, in build/pack") // Defining these settings is somewhat redundant as we also redefine settings that depend on them. // However, IntelliJ's project import works better when these are set correctly. @@ -929,7 +1006,7 @@ intellij := { def moduleDep(name: String, jars: Seq[File]) = { val entries = jars.map(f => s""" """).mkString("\n") - s"""| + s"""| | |$entries | diff --git a/project/BuildSettings.scala b/project/BuildSettings.scala new file mode 100644 index 000000000000..76cd888a2d43 --- /dev/null +++ b/project/BuildSettings.scala @@ -0,0 +1,11 @@ +import sbt._ + +/** This object defines keys that should be visible with an unqualified name in all .sbt files and the command line */ +object BuildSettings extends AutoPlugin { + object autoImport { + lazy val antStyle = settingKey[Boolean]("Use ant-style incremental builds instead of name-hashing") + lazy val baseVersion = settingKey[String]("The base version number from which all others are derived") + lazy val baseVersionSuffix = settingKey[String]("Identifies the kind of version to build") + lazy val mimaReferenceVersion = settingKey[Option[String]]("Scala version number to run MiMa against") + } +} diff --git a/project/MiMa.scala b/project/MiMa.scala new file mode 100644 index 000000000000..66442fc7256a --- /dev/null +++ b/project/MiMa.scala @@ -0,0 +1,95 @@ +// It would be nice to use sbt-mima-plugin here, but the plugin is missing +// at least two features we need: +// * ability to run MiMa twice, swapping `curr` and `prev`, to detect +// both forwards and backwards incompatibilities (possibly fixed as of +// https://github.com/typesafehub/migration-manager/commit/2844ffa48b6d2255aa64bd687703aec21dadd55e) +// * ability to pass a filter file (https://github.com/typesafehub/migration-manager/issues/102) +// So we invoke the MiMa CLI directly; it's also what the Ant build did. + +import sbt._ +import sbt.Keys._ +import BuildSettings.autoImport._ + +object MiMa { + lazy val mima = + taskKey[Unit]("run Migration Manager to detect binary incompatibilities") + + lazy val settings = + Seq( + mima := { + val log = streams.value.log + mimaReferenceVersion.value.fold { + log.info(s"No reference version defined - skipping binary compatibility checks") + } { refVersion => + def runOnce(prev: java.io.File, curr: java.io.File, isForward: Boolean): Unit = { + val direction = if (isForward) "forward" else "backward" + log.info(s"Checking $direction binary compatibility") + log.debug(s"prev = $prev, curr = $curr") + runMima( + prev = if (isForward) curr else prev, + curr = if (isForward) prev else curr, + // TODO: it would be nicer if each subproject had its own whitelist, but for now + // for compatibility with how Ant did things, there's just one at the root. + // once Ant is gone we'd be free to split it up. + filter = (baseDirectory in ThisBuild).value / s"bincompat-$direction.whitelist.conf", + log) + } + val artifact = + getPreviousArtifact( + "org.scala-lang" % s"${name.value}" % refVersion, + ivySbt.value, streams.value) + for (isForward <- Seq(false, true)) + runOnce(artifact, (packageBin in Compile).value, isForward) + } + } + ) + + def runMima(prev: java.io.File, curr: java.io.File, filter: java.io.File, log: Logger): Unit = { + val args = Array( + "--prev", prev.getAbsolutePath, + "--curr", curr.getAbsolutePath, + "--filters", filter.getAbsolutePath, + "--generate-filters" + ) + val exitCode = TrapExit(com.typesafe.tools.mima.cli.Main.main(args), log) + if (exitCode != 0) + throw new RuntimeException(s"MiMa failed with exit code $exitCode") + } + + // cribbed from https://github.com/typesafehub/migration-manager/blob/master/sbtplugin/src/main/scala/com/typesafe/tools/mima/plugin/SbtMima.scala + def getPreviousArtifact(m: ModuleID, ivy: IvySbt, s: TaskStreams): File = { + val moduleSettings = InlineConfiguration( + "dummy" % "test" % "version", + ModuleInfo("dummy-test-project-for-resolving"), + dependencies = Seq(m)) + val module = new ivy.Module(moduleSettings) + val report = Deprecated.Inner.ivyUpdate(ivy)(module, s) + val optFile = (for { + config <- report.configurations + module <- config.modules + (artifact, file) <- module.artifacts + // TODO - Hardcode this? + if artifact.name == m.name + } yield file).headOption + optFile getOrElse sys.error("Could not resolve previous artifact: " + m) + } + +} + +// use the SI-7934 workaround to silence a deprecation warning on an sbt API +// we have no choice but to call. on the lack of any suitable alternative, +// see https://gitter.im/sbt/sbt-dev?at=5616e2681b0e279854bd74a4 : +// "it's my intention to eventually come up with a public API" says Eugene Y +object Deprecated { + @deprecated("", "") class Inner { + def ivyUpdate(ivy: IvySbt)(module: ivy.Module, s: TaskStreams) = + IvyActions.update( + module, + new UpdateConfiguration( + retrieve = None, + missingOk = false, + logging = UpdateLogging.DownloadOnly), + s.log) + } + object Inner extends Inner +} diff --git a/project/Osgi.scala b/project/Osgi.scala index d780be2f78ed..b557df1688f3 100644 --- a/project/Osgi.scala +++ b/project/Osgi.scala @@ -28,8 +28,8 @@ object Osgi { "Bundle-Name" -> bundleName.value, "Bundle-SymbolicName" -> bundleSymbolicName.value, "ver" -> v, - "Export-Package" -> ("*;version=${ver}"), - "Import-Package" -> ("scala.*;version=\"${range;[==,=+);${ver}}\",*"), + "Export-Package" -> "*;version=${ver}", + "Import-Package" -> "scala.*;version=\"${range;[==,=+);${ver}}\",*", "Bundle-Version" -> v, "Bundle-RequiredExecutionEnvironment" -> "JavaSE-1.6, JavaSE-1.7", "-eclipse" -> "false" diff --git a/project/Quiet.scala b/project/Quiet.scala index de30ebe6abac..84d01d5544b9 100644 --- a/project/Quiet.scala +++ b/project/Quiet.scala @@ -28,6 +28,4 @@ object Quiet { case x => x } } - - def silenceIvyUpdateInfoLogging = logLevel in update := Level.Warn } diff --git a/project/ScalaTool.scala b/project/ScalaTool.scala index e9531f229eee..5e3f20b1ba61 100644 --- a/project/ScalaTool.scala +++ b/project/ScalaTool.scala @@ -27,12 +27,12 @@ case class ScalaTool(mainClass: String, } else classpath.mkString(":").replace('\\', '/').replaceAll(varRegex, """\${$1}""") val variables = Map( - ("@@" -> "@"), // for backwards compatibility - ("@class@" -> mainClass), - ("@properties@" -> (properties map { case (k, v) => s"""-D$k="$v""""} mkString " ")), - ("@javaflags@" -> javaOpts), - ("@toolflags@" -> toolFlags), - ("@classpath@" -> platformClasspath) + "@@" -> "@", // for backwards compatibility + "@class@" -> mainClass, + "@properties@" -> (properties map { case (k, v) => s"""-D$k="$v""""} mkString " "), + "@javaflags@" -> javaOpts, + "@toolflags@" -> toolFlags, + "@classpath@" -> platformClasspath ) val (from, to) = variables.unzip diff --git a/project/ScriptCommands.scala b/project/ScriptCommands.scala index 537990d9853c..efeac95e6de3 100644 --- a/project/ScriptCommands.scala +++ b/project/ScriptCommands.scala @@ -1,19 +1,32 @@ import sbt._ import Keys._ -import complete.DefaultParsers._ +import BuildSettings.autoImport._ /** Custom commands for use by the Jenkins scripts. This keeps the surface area and call syntax small. */ object ScriptCommands { - def all = Seq(setupPublishCore) + def all = Seq(setupPublishCore, setupValidateTest) /** Set up the environment for `validate/publish-core`. The argument is the Artifactory snapshot repository URL. */ def setupPublishCore = Command.single("setupPublishCore") { case (state, url) => Project.extract(state).append(Seq( - VersionUtil.baseVersionSuffix in Global := "SHA-SNAPSHOT", + baseVersionSuffix in Global := "SHA-SNAPSHOT", // Append build.timestamp to Artifactory URL to get consistent build numbers (see https://github.com/sbt/sbt/issues/2088): publishTo in Global := Some("scala-pr" at url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis), publishArtifact in (Compile, packageDoc) in ThisBuild := false, - scalacOptions in Compile in ThisBuild += "-optimise" + scalacOptions in Compile in ThisBuild += "-optimise", + logLevel in ThisBuild := Level.Info, + logLevel in update in ThisBuild := Level.Warn ), state) } + + /** Set up the environment for `validate/test`. The argument is the Artifactory snapshot repository URL. */ + def setupValidateTest = Command.single("setupValidateTest") { case (state, url) => + //TODO When ant is gone, pass starr version as an argument to this command instead of using version.properties + Project.extract(state).append(Seq( + resolvers in Global += "scala-pr" at url, + scalacOptions in Compile in ThisBuild += "-optimise", + logLevel in ThisBuild := Level.Info, + logLevel in update in ThisBuild := Level.Warn + ), state) + } } diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala index 6c8aebf74fab..4705bbb6ce36 100644 --- a/project/VersionUtil.scala +++ b/project/VersionUtil.scala @@ -1,12 +1,11 @@ import sbt._ import Keys._ import java.util.Properties -import java.io.FileInputStream +import java.io.{File, FileInputStream} import scala.collection.JavaConverters._ +import BuildSettings.autoImport._ object VersionUtil { - lazy val baseVersion = settingKey[String]("The base version number from which all others are derived") - lazy val baseVersionSuffix = settingKey[String]("Identifies the kind of version to build") lazy val copyrightString = settingKey[String]("Copyright string.") lazy val versionProperties = settingKey[Versions]("Version properties.") lazy val generateVersionPropertiesFile = taskKey[File]("Generating version properties file.") @@ -123,4 +122,33 @@ object VersionUtil { /** Get a subproject version number from `versionProps` */ def versionNumber(name: String): String = versionProps(s"$name.version.number") + + /** Build a dependency to a Scala module with the given group and artifact ID */ + def scalaDep(group: String, artifact: String, versionProp: String = null, scope: String = null, compatibility: String = "binary") = { + val vp = if(versionProp eq null) artifact else versionProp + val m = group % (artifact + "_" + versionProps(s"scala.$compatibility.version")) % versionNumber(vp) + val m2 = if(scope eq null) m else m % scope + // exclusion of the scala-library transitive dependency avoids eviction warnings during `update`: + m2.exclude("org.scala-lang", "*") + } + + private def bootstrapOrganization(path: String) = + "org.scala-lang.scala-sha-bootstrap." + path.replace('/', '.') + + /** Build a dependency to a JAR file in the bootstrap repository */ + def bootstrapDep(baseDir: File, path: String, libName: String): ModuleID = { + val sha = IO.read(baseDir / path / s"$libName.jar.desired.sha1").split(' ')(0) + bootstrapOrganization(path) % libName % sha from + s"https://dl.bintray.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap/$sha/$path/$libName.jar" + } + + /** Copy a boostrap dependency JAR that is on the classpath to a file */ + def copyBootstrapJar(cp: Seq[Attributed[File]], baseDir: File, path: String, libName: String): Unit = { + val org = bootstrapOrganization(path) + val resolved = cp.find { a => + val mod = a.get(moduleID.key) + mod.map(_.organization) == Some(org) && mod.map(_.name) == Some(libName) + }.map(_.data).get + IO.copyFile(resolved, baseDir / path / s"$libName.jar") + } } diff --git a/project/plugins.sbt b/project/plugins.sbt index 46203565b483..4c0a6e7b8a3f 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,6 @@ +scalacOptions ++= Seq("-unchecked", "-feature", /*"-deprecation",*/ + "-Xlint" /*, "-Xfatal-warnings"*/) + libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.3.2" libraryDependencies += "org.pantsbuild" % "jarjar" % "1.6.3" @@ -15,3 +18,5 @@ buildClasspath := (externalDependencyClasspath in Compile).value.map(_.data).mkS buildInfoKeys := Seq[BuildInfoKey](buildClasspath) buildInfoPackage := "scalabuild" + +libraryDependencies += "com.typesafe" %% "mima-reporter" % "0.1.8" diff --git a/scripts/jobs/validate/publish-core b/scripts/jobs/validate/publish-core index bb0056722dc0..b0bfd480836a 100755 --- a/scripts/jobs/validate/publish-core +++ b/scripts/jobs/validate/publish-core @@ -16,7 +16,7 @@ case $prDryRun in ;; *) echo ">>> Getting Scala version number." - $SBT_CMD "setupPublishCore $prRepoUrl" generateBuildCharacterPropertiesFile + $SBT_CMD --warn "setupPublishCore $prRepoUrl" generateBuildCharacterPropertiesFile parseScalaProperties buildcharacter.properties # produce maven_version_number echo ">>> Checking availability of Scala ${maven_version_number} in $prRepoUrl." @@ -27,7 +27,7 @@ case $prDryRun in if $libraryAvailable && $reflectAvailable && $compilerAvailable; then echo "Scala core already built!" else - $SBT_CMD "setupPublishCore $prRepoUrl" $antBuildArgs publish + $SBT_CMD --warn "setupPublishCore $prRepoUrl" publish fi mv buildcharacter.properties jenkins.properties # parsed by the jenkins job diff --git a/scripts/jobs/validate/test b/scripts/jobs/validate/test index bedef2e458b9..3cd8af56081b 100755 --- a/scripts/jobs/validate/test +++ b/scripts/jobs/validate/test @@ -1,17 +1,36 @@ -#!/bin/bash -e +#!/bin/bash -e -v -x + +baseDir=${WORKSPACE-`pwd`} +scriptsDir="$baseDir/scripts" +. $scriptsDir/common case $prDryRun in + yep) echo "DRY RUN" ;; + *) - ./pull-binary-libs.sh # build quick using STARR built upstream, as specified by scalaVersion - # (in that sense it's locker, since it was built with starr by that upstream job) - ant -Dstarr.version=$scalaVersion \ - -Dscalac.args.optimise=-optimise \ - -Dlocker.skip=1 -Dextra.repo.url=$prRepoUrl \ - $testExtraArgs ${testTarget-test.core docs.done} + # (in that sense it's locker, since it was built with starr by that upstream job); + # and run JUnit tests, partest, OSGi tests, MiMa and scaladoc + $SBT_CMD \ + -Dstarr.version=$scalaVersion \ + --warn \ + "setupValidateTest $prRepoUrl" \ + $testExtraArgs \ + "test" \ + "partest run pos neg jvm" \ + "partest res scalap specialized scalacheck" \ + "partest instrumented presentation" \ + "partest --srcpath scaladoc" \ + osgiTestFelix/test \ + osgiTestEclipse/test \ + library/mima \ + reflect/mima \ + doc + ;; -esac \ No newline at end of file + +esac diff --git a/src/scaladoc/scala/tools/nsc/doc/model/MemberLookup.scala b/src/scaladoc/scala/tools/nsc/doc/model/MemberLookup.scala index 64eb1adbea24..a649c175d068 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/MemberLookup.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/MemberLookup.scala @@ -44,8 +44,22 @@ trait MemberLookup extends base.MemberLookupBase { /* Get package object which has associatedFile ne null */ sym.info.member(newTermName("package")) else sym - Option(sym1.associatedFile) flatMap (_.underlyingSource) flatMap { src => - val path = src.canonicalPath + def classpathEntryFor(s: Symbol): Option[String] = { + Option(s.associatedFile).flatMap(_.underlyingSource).map { src => + val path = src.canonicalPath + if(path.endsWith(".class")) { // Individual class file -> Classpath entry is root dir + var nesting = s.ownerChain.count(_.hasPackageFlag) + if(nesting > 0) { + val p = 0.until(nesting).foldLeft(src) { + case (null, _) => null + case (f, _) => f.container + } + if(p eq null) path else p.canonicalPath + } else path + } else path // JAR file (and fallback option) + } + } + classpathEntryFor(sym1) flatMap { path => settings.extUrlMapping get path map { url => LinkToExternal(name, url + "#" + name) } diff --git a/test/files/run/t7843-jsr223-service.check b/test/disabled/run/t7843-jsr223-service.check similarity index 100% rename from test/files/run/t7843-jsr223-service.check rename to test/disabled/run/t7843-jsr223-service.check diff --git a/test/files/run/t7843-jsr223-service.scala b/test/disabled/run/t7843-jsr223-service.scala similarity index 100% rename from test/files/run/t7843-jsr223-service.scala rename to test/disabled/run/t7843-jsr223-service.scala diff --git a/test/files/run/t7933.check b/test/disabled/run/t7933.check similarity index 100% rename from test/files/run/t7933.check rename to test/disabled/run/t7933.check diff --git a/test/files/run/t7933.scala b/test/disabled/run/t7933.scala similarity index 100% rename from test/files/run/t7933.scala rename to test/disabled/run/t7933.scala diff --git a/test/osgi/src/logback.xml b/test/osgi/src/logback.xml new file mode 100644 index 000000000000..692ccbfdd9c3 --- /dev/null +++ b/test/osgi/src/logback.xml @@ -0,0 +1,10 @@ + + + + *** \(%logger{30}\)%green(%X{debugId}) %msg%n + + + + + + diff --git a/test/scaladoc/.gitignore b/test/scaladoc/.gitignore new file mode 100644 index 000000000000..161be5b55fad --- /dev/null +++ b/test/scaladoc/.gitignore @@ -0,0 +1,2 @@ +*.log +*.obj/ diff --git a/test/scaladoc/run/SI-191.scala b/test/scaladoc/run/SI-191.scala index 29b1e7dd29ee..f3d269ceb0e9 100644 --- a/test/scaladoc/run/SI-191.scala +++ b/test/scaladoc/run/SI-191.scala @@ -33,10 +33,14 @@ object Test extends ScaladocModelTest { def scalaURL = "http://bog.us" override def scaladocSettings = { - val scalaLibUri = getClass.getClassLoader.getResource("scala/Function1.class").getPath.split("!")(0) - val scalaLibPath = new URI(scalaLibUri).getPath - val externalArg = s"$scalaLibPath#$scalaURL" - "-no-link-warnings -doc-external-doc " + externalArg + val samplePath = getClass.getClassLoader.getResource("scala/Function1.class").getPath + val scalaLibPath = if(samplePath.contains("!")) { // in scala-library.jar + val scalaLibUri = samplePath.split("!")(0) + new URI(scalaLibUri).getPath + } else { // individual class files on disk + samplePath.replace('\\', '/').dropRight("scala/Function1.class".length) + } + s"-no-link-warnings -doc-external-doc $scalaLibPath#$scalaURL" } def testModel(rootPackage: Package) { diff --git a/test/scaladoc/run/t8557.scala b/test/scaladoc/run/t8557.scala index 451f004d7d43..7876896bb7ea 100644 --- a/test/scaladoc/run/t8557.scala +++ b/test/scaladoc/run/t8557.scala @@ -1,3 +1,5 @@ +import java.net.URI + import scala.tools.nsc.doc.base._ import scala.tools.nsc.doc.model._ import scala.tools.partest.ScaladocModelTest @@ -15,10 +17,22 @@ object Test extends ScaladocModelTest { class A """ + def scalaURL = "http://www.scala-lang.org/api/current/" + // a non-canonical path to scala-library.jar should still work - // this is a bit fragile (depends on the current directory being the root of the repo ; - // ant & partest seem to do that properly) - def scaladocSettings = "-doc-external-doc build/pack/bin/../lib/scala-library.jar#http://www.scala-lang.org/api/current/" + override def scaladocSettings = { + val samplePath = getClass.getClassLoader.getResource("scala/Function1.class").getPath.replace('\\', '/') + val scalaLibPath = if(samplePath.contains("!")) { // in scala-library.jar + val scalaLibUri = samplePath.split("!")(0) + val p = new URI(scalaLibUri).getPath + // this is a bit fragile (depends on the scala library being in build/pack as produced by ant) + p.replace("/pack/lib/scala-library.jar", "/pack/bin/../lib/scala-library.jar") + } else { // individual class files on disk + val p = samplePath.dropRight("scala/Function1.class".length + 1) + p + "/.." + p.takeRight(p.length - p.lastIndexOf('/')) + } + s"-doc-external-doc $scalaLibPath#$scalaURL" + } def testModel(rootPackage: Package) = { // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s)) diff --git a/versions.properties b/versions.properties index afea93f666f1..9cfd3598000c 100644 --- a/versions.properties +++ b/versions.properties @@ -36,7 +36,7 @@ jline.version=2.12.1 scala-asm.version=5.0.4-scala-3 # external modules, used internally (not shipped) -partest.version.number=1.0.13 +partest.version.number=1.0.16 scalacheck.version.number=1.11.6 # TODO: modularize the compiler From c2c08a45a99f6ba48d8dc3b7c06d44196e50a2a2 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Tue, 14 Jun 2016 16:27:01 +0200 Subject: [PATCH 103/153] Remove bnd warnings from log output --- project/Osgi.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Osgi.scala b/project/Osgi.scala index b557df1688f3..c5d4734cab8f 100644 --- a/project/Osgi.scala +++ b/project/Osgi.scala @@ -28,7 +28,7 @@ object Osgi { "Bundle-Name" -> bundleName.value, "Bundle-SymbolicName" -> bundleSymbolicName.value, "ver" -> v, - "Export-Package" -> "*;version=${ver}", + "Export-Package" -> "*;version=${ver};-split-package:=merge-first", "Import-Package" -> "scala.*;version=\"${range;[==,=+);${ver}}\",*", "Bundle-Version" -> v, "Bundle-RequiredExecutionEnvironment" -> "JavaSE-1.6, JavaSE-1.7", From 8eaa53d57c8d3346e03ccde7b7d4c4c8103d9253 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 16 Jun 2016 00:43:51 -0700 Subject: [PATCH 104/153] Avoid triple-quoting triple quotes The boolean test for triples was inadvertently flipped. Adds test for pretty printed multiline strings --- src/reflect/scala/reflect/internal/Printers.scala | 2 +- test/junit/scala/reflect/internal/PrintersTest.scala | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 37b99c4345f6..4ad34ff8c789 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -1050,7 +1050,7 @@ trait Printers extends api.Printers { self: SymbolTable => x match { case Constant(v: String) if { val strValue = x.stringValue - strValue.contains(LF) && strValue.contains("\"\"\"") && strValue.size > 1 + strValue.contains(LF) && !strValue.contains("\"\"\"") && strValue.size > 1 } => val splitValue = x.stringValue.split(s"$LF").toList val multilineStringValue = if (x.stringValue.endsWith(s"$LF")) splitValue :+ "" else splitValue diff --git a/test/junit/scala/reflect/internal/PrintersTest.scala b/test/junit/scala/reflect/internal/PrintersTest.scala index 2305e7ea50de..916f21adc876 100644 --- a/test/junit/scala/reflect/internal/PrintersTest.scala +++ b/test/junit/scala/reflect/internal/PrintersTest.scala @@ -79,6 +79,14 @@ class BasePrintTest { @Test def testConstantLong = assertTreeCode(Literal(Constant(42l)))("42L") + @Test def testConstantMultiline = assertTreeCode(Literal(Constant("hello\nworld")))("\"\"\"hello\nworld\"\"\"") + + val sq = "\"" + val teq = "\\\"" * 3 + val tq = "\"" * 3 + + @Test def testConstantEmbeddedTriple = assertTreeCode(Literal(Constant(s"${tq}hello${tq}\nworld")))(s"${sq}${teq}hello${teq}\\nworld${sq}") + @Test def testOpExpr = assertPrintedCode("(5).+(4)", checkTypedTree = false) @Test def testName1 = assertPrintedCode("class test") From 14d3b9e7062662ae55cca02ad653a68aa6aef78d Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 16 Jun 2016 09:52:20 -0700 Subject: [PATCH 105/153] Refactor triple quote quoting To quote a triple quote, only quote one quote. Refactors the code for legibility. Adds test for other inline cruft like control chars. --- .../scala/reflect/internal/Printers.scala | 30 +++++++++---------- .../scala/reflect/internal/PrintersTest.scala | 12 +++++--- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 4ad34ff8c789..9602a2859bd6 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -1045,23 +1045,23 @@ trait Printers extends api.Printers { self: SymbolTable => print("") } - case l @ Literal(x) => - import Chars.LF - x match { - case Constant(v: String) if { - val strValue = x.stringValue - strValue.contains(LF) && !strValue.contains("\"\"\"") && strValue.size > 1 - } => - val splitValue = x.stringValue.split(s"$LF").toList - val multilineStringValue = if (x.stringValue.endsWith(s"$LF")) splitValue :+ "" else splitValue - val trQuotes = "\"\"\"" - print(trQuotes); printSeq(multilineStringValue) { print(_) } { print(LF) }; print(trQuotes) - case _ => - // processing Float constants - val printValue = x.escapedStringValue + (if (x.value.isInstanceOf[Float]) "F" else "") - print(printValue) + case Literal(k @ Constant(s: String)) if s.contains(Chars.LF) => + val tq = "\"" * 3 + val lines = s.lines.toList + if (lines.lengthCompare(1) <= 0) print(k.escapedStringValue) + else { + val tqp = """["]{3}""".r + val tqq = """""\\"""" // ""\" is triple-quote quoted + print(tq) + printSeq(lines.map(x => tqp.replaceAllIn(x, tqq)))(print(_))(print(Chars.LF)) + print(tq) } + case Literal(x) => + // processing Float constants + val suffix = x.value match { case _: Float => "F" case _ => "" } + print(s"${x.escapedStringValue}${suffix}") + case an @ Annotated(ap, tree) => val printParentheses = needsParentheses(tree)() parenthesize(printParentheses) { print(tree) }; print(if (tree.isType) " " else ": ") diff --git a/test/junit/scala/reflect/internal/PrintersTest.scala b/test/junit/scala/reflect/internal/PrintersTest.scala index 916f21adc876..38fe205af764 100644 --- a/test/junit/scala/reflect/internal/PrintersTest.scala +++ b/test/junit/scala/reflect/internal/PrintersTest.scala @@ -79,13 +79,17 @@ class BasePrintTest { @Test def testConstantLong = assertTreeCode(Literal(Constant(42l)))("42L") - @Test def testConstantMultiline = assertTreeCode(Literal(Constant("hello\nworld")))("\"\"\"hello\nworld\"\"\"") - val sq = "\"" - val teq = "\\\"" * 3 val tq = "\"" * 3 + val teq = "\"\"\\\"" + + @Test def testConstantMultiline = assertTreeCode(Literal(Constant("hello\nworld")))(s"${tq}hello\nworld${tq}") + + @Test def testConstantFormfeed = assertTreeCode(Literal(Constant("hello\fworld")))(s"${sq}hello\\fworld${sq}") + + @Test def testConstantControl = assertTreeCode(Literal(Constant("hello\u0003world")))(s"${sq}hello\\03world${sq}") - @Test def testConstantEmbeddedTriple = assertTreeCode(Literal(Constant(s"${tq}hello${tq}\nworld")))(s"${sq}${teq}hello${teq}\\nworld${sq}") + @Test def testConstantEmbeddedTriple = assertTreeCode(Literal(Constant(s"${tq}hello${tq}\nworld")))(s"${tq}${teq}hello${teq}\nworld${tq}") @Test def testOpExpr = assertPrintedCode("(5).+(4)", checkTypedTree = false) From 0eac3cb85dd4720b015a0d060691f68b63032b85 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 16 Jun 2016 10:15:56 -0700 Subject: [PATCH 106/153] Constant print control in unicode Since octal escape is deprecated, use unicode escape for string representation of constants. --- src/reflect/scala/reflect/internal/Constants.scala | 3 +-- test/files/run/reflection-java-annotations.check | 5 ++--- test/files/run/reflection-java-annotations/Test_2.scala | 4 ++-- test/junit/scala/reflect/internal/PrintersTest.scala | 6 +++++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Constants.scala b/src/reflect/scala/reflect/internal/Constants.scala index 85d0efdcba79..7b47798ff725 100644 --- a/src/reflect/scala/reflect/internal/Constants.scala +++ b/src/reflect/scala/reflect/internal/Constants.scala @@ -7,7 +7,6 @@ package scala package reflect package internal -import java.lang.Integer.toOctalString import scala.annotation.switch trait Constants extends api.Constants { @@ -212,7 +211,7 @@ trait Constants extends api.Constants { case '"' => "\\\"" case '\'' => "\\\'" case '\\' => "\\\\" - case _ => if (ch.isControl) "\\0" + toOctalString(ch.toInt) else String.valueOf(ch) + case _ => if (ch.isControl) "\\u%04X".format(ch.toInt) else String.valueOf(ch) } def escapedStringValue: String = { diff --git a/test/files/run/reflection-java-annotations.check b/test/files/run/reflection-java-annotations.check index 67317d20729e..4c20727ea8fd 100644 --- a/test/files/run/reflection-java-annotations.check +++ b/test/files/run/reflection-java-annotations.check @@ -1,4 +1,3 @@ -warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details -List(JavaComplexAnnotation_1(v1 = 1, v10 = "hello", v101 = [101, 101], v102 = [102, 102], v103 = ['g', 'g'], v104 = [104, 104], v105 = [105L, 105L], v106 = [106.0, 106.0], v107 = [107.0, 107.0], v108 = [false, true], v11 = classOf[JavaAnnottee_1], v110 = ["hello", "world"], v111 = [classOf[JavaSimpleAnnotation_1], classOf[JavaComplexAnnotation_1]], v112 = [FOO, BAR], v113 = [JavaSimpleAnnotation_1(v1 = 21, v10 = "world2", v11 = classOf[JavaComplexAnnotation_1], v12 = BAR, v2 = 22, v3 = '\027', v4 = 24, v5 = 25L, v6 = 26.0, v7 = 27.0, v8 = false)], v12 = FOO, v13 = JavaSimpleAnnotation_1(v1 = 11, v10 = "world1", v11 = classOf[JavaSimpleAnnotation_1], v12 = FOO, v2 = 12, v3 = '\r', v4 = 14, v5 = 15L, v6 = 16.0, v7 = 17.0, v8 = false), v2 = 2, v3 = '\03', v4 = 4, v5 = 5L, v6 = 6.0, v7 = 7.0, v8 = false)) +List(JavaComplexAnnotation_1(v1 = 1, v10 = "hello", v101 = [101, 101], v102 = [102, 102], v103 = ['g', 'g'], v104 = [104, 104], v105 = [105L, 105L], v106 = [106.0, 106.0], v107 = [107.0, 107.0], v108 = [false, true], v11 = classOf[JavaAnnottee_1], v110 = ["hello", "world"], v111 = [classOf[JavaSimpleAnnotation_1], classOf[JavaComplexAnnotation_1]], v112 = [FOO, BAR], v113 = [JavaSimpleAnnotation_1(v1 = 21, v10 = "world2", v11 = classOf[JavaComplexAnnotation_1], v12 = BAR, v2 = 22, v3 = '\u0017', v4 = 24, v5 = 25L, v6 = 26.0, v7 = 27.0, v8 = false)], v12 = FOO, v13 = JavaSimpleAnnotation_1(v1 = 11, v10 = "world1", v11 = classOf[JavaSimpleAnnotation_1], v12 = FOO, v2 = 12, v3 = '\r', v4 = 14, v5 = 15L, v6 = 16.0, v7 = 17.0, v8 = false), v2 = 2, v3 = '\u0003', v4 = 4, v5 = 5L, v6 = 6.0, v7 = 7.0, v8 = false)) ======= -new JavaComplexAnnotation_1(v1 = 1, v10 = "hello", v101 = Array(101, 101), v102 = Array(102, 102), v103 = Array('g', 'g'), v104 = Array(104, 104), v105 = Array(105L, 105L), v106 = Array(106.0, 106.0), v107 = Array(107.0, 107.0), v108 = Array(false, true), v11 = classOf[JavaAnnottee_1], v110 = Array("hello", "world"), v111 = Array(classOf[JavaSimpleAnnotation_1], classOf[JavaComplexAnnotation_1]), v112 = Array(FOO, BAR), v113 = Array(new JavaSimpleAnnotation_1(v1 = 21, v10 = "world2", v11 = classOf[JavaComplexAnnotation_1], v12 = BAR, v2 = 22, v3 = '\027', v4 = 24, v5 = 25L, v6 = 26.0, v7 = 27.0, v8 = false)), v12 = FOO, v13 = new JavaSimpleAnnotation_1(v1 = 11, v10 = "world1", v11 = classOf[JavaSimpleAnnotation_1], v12 = FOO, v2 = 12, v3 = '\r', v4 = 14, v5 = 15L, v6 = 16.0, v7 = 17.0, v8 = false), v2 = 2, v3 = '\03', v4 = 4, v5 = 5L, v6 = 6.0, v7 = 7.0, v8 = false) +new JavaComplexAnnotation_1(v1 = 1, v10 = "hello", v101 = Array(101, 101), v102 = Array(102, 102), v103 = Array('g', 'g'), v104 = Array(104, 104), v105 = Array(105L, 105L), v106 = Array(106.0, 106.0), v107 = Array(107.0, 107.0), v108 = Array(false, true), v11 = classOf[JavaAnnottee_1], v110 = Array("hello", "world"), v111 = Array(classOf[JavaSimpleAnnotation_1], classOf[JavaComplexAnnotation_1]), v112 = Array(FOO, BAR), v113 = Array(new JavaSimpleAnnotation_1(v1 = 21, v10 = "world2", v11 = classOf[JavaComplexAnnotation_1], v12 = BAR, v2 = 22, v3 = '\u0017', v4 = 24, v5 = 25L, v6 = 26.0, v7 = 27.0, v8 = false)), v12 = FOO, v13 = new JavaSimpleAnnotation_1(v1 = 11, v10 = "world1", v11 = classOf[JavaSimpleAnnotation_1], v12 = FOO, v2 = 12, v3 = '\r', v4 = 14, v5 = 15L, v6 = 16.0, v7 = 17.0, v8 = false), v2 = 2, v3 = '\u0003', v4 = 4, v5 = 5L, v6 = 6.0, v7 = 7.0, v8 = false) diff --git a/test/files/run/reflection-java-annotations/Test_2.scala b/test/files/run/reflection-java-annotations/Test_2.scala index dec5b45ca74e..6d457ebe64f5 100644 --- a/test/files/run/reflection-java-annotations/Test_2.scala +++ b/test/files/run/reflection-java-annotations/Test_2.scala @@ -2,8 +2,8 @@ object Test extends App { import scala.reflect.runtime.universe._ val sym = typeOf[JavaAnnottee_1].typeSymbol sym.info - sym.annotations foreach (_.javaArgs) + sym.annotations foreach (_.tree.children.tail) println(sym.annotations) println("=======") sym.annotations.map(_.tree).map(println) -} \ No newline at end of file +} diff --git a/test/junit/scala/reflect/internal/PrintersTest.scala b/test/junit/scala/reflect/internal/PrintersTest.scala index 38fe205af764..d581ca8cf432 100644 --- a/test/junit/scala/reflect/internal/PrintersTest.scala +++ b/test/junit/scala/reflect/internal/PrintersTest.scala @@ -87,7 +87,11 @@ class BasePrintTest { @Test def testConstantFormfeed = assertTreeCode(Literal(Constant("hello\fworld")))(s"${sq}hello\\fworld${sq}") - @Test def testConstantControl = assertTreeCode(Literal(Constant("hello\u0003world")))(s"${sq}hello\\03world${sq}") + @Test def testConstantControl = assertTreeCode(Literal(Constant("hello\u0003world")))(s"${sq}hello\\u0003world${sq}") + + @Test def testConstantFormfeedChar = assertTreeCode(Literal(Constant('\f')))("'\\f'") + + @Test def testConstantControlChar = assertTreeCode(Literal(Constant(3.toChar)))("'\\u0003'") @Test def testConstantEmbeddedTriple = assertTreeCode(Literal(Constant(s"${tq}hello${tq}\nworld")))(s"${tq}${teq}hello${teq}\nworld${tq}") From cf0390d94e59c637ba83170232864b069b90474e Mon Sep 17 00:00:00 2001 From: Dmitriy Pogretskiy Date: Tue, 14 Jun 2016 15:08:57 +0300 Subject: [PATCH 107/153] SI-9817 forall and exists SI-9817 Immutable queue formatting SI-9817 Added comments SI-9817 Comment formatting --- src/library/scala/collection/immutable/Queue.scala | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 3ad6656636d8..1dd0d7683a07 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -84,6 +84,14 @@ sealed class Queue[+A] protected(protected val in: List[A], protected val out: L else if (in.nonEmpty) new Queue(Nil, in.reverse.tail) else throw new NoSuchElementException("tail on empty queue") + /* This is made to avoid inefficient implementation of iterator. */ + override def forall(p: A => Boolean): Boolean = + in.forall(p) && out.forall(p) + + /* This is made to avoid inefficient implementation of iterator. */ + override def exists(p: A => Boolean): Boolean = + in.exists(p) || out.exists(p) + /** Returns the length of the queue. */ override def length = in.length + out.length From 2d85fe47fddd3759db37e0106920688dcbceb7ef Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 21 Jun 2016 12:07:06 +0200 Subject: [PATCH 108/153] Fix test failures of the sbt build in 2.12.x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - More memory for compiling partest tests - Enable more detailed logging for partest failures: Partest’s `AntRunner` has extra code for logging details of all failed tests at the end of a run which is not present in `SbtRunner` but we can set the `--show-log` and `--show-diff` options to get similar output interspersed with the main test log. - Update OSGi test dependencies for sbt build to same versions as in ant (see 8247b8f077c96ba9a017b53de4d8062fe428c4a7 for the motivation for this change). - Disable MiMa checks (to be reactivated after M5). --- build.sbt | 23 +++++++++++------------ project/ScriptCommands.scala | 1 + 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.sbt b/build.sbt index 98ea8f0b3266..20ae42b3e6b1 100644 --- a/build.sbt +++ b/build.sbt @@ -112,7 +112,7 @@ lazy val publishSettings : Seq[Setting[_]] = Seq( globalVersionSettings baseVersion in Global := "2.12.0" baseVersionSuffix in Global := "SNAPSHOT" -mimaReferenceVersion in Global := Some("2.11.0") +mimaReferenceVersion in Global := None lazy val commonSettings = clearSourceAndResourceDirectories ++ publishSettings ++ Seq[Setting[_]]( organization := "org.scala-lang", @@ -567,11 +567,11 @@ lazy val junit = project.in(file("test") / "junit") lazy val osgiTestFelix = osgiTestProject( project.in(file(".") / "target" / "osgiTestFelix"), - "org.apache.felix" % "org.apache.felix.framework" % "4.4.0") + "org.apache.felix" % "org.apache.felix.framework" % "5.0.1") lazy val osgiTestEclipse = osgiTestProject( project.in(file(".") / "target" / "osgiTestEclipse"), - "org.eclipse.osgi" % "org.eclipse.osgi" % "3.7.1") + "org.eclipse.tycho" % "org.eclipse.osgi" % "3.10.100.v20150521-1310") def osgiTestProject(p: Project, framework: ModuleID) = p .dependsOn(library, reflect, compiler) @@ -583,19 +583,18 @@ def osgiTestProject(p: Project, framework: ModuleID) = p fork in Test := true, parallelExecution in Test := false, libraryDependencies ++= { - val paxExamVersion = "3.5.0" // Last version which supports Java 6 + val paxExamVersion = "4.5.0" // Last version which supports Java 6 Seq( junitDep, junitInterfaceDep, - "org.ops4j.pax.exam" % "pax-exam-container-native" % paxExamVersion - exclude("org.osgi", "org.osgi.core"), // Avoid dragging in a dependency which requires Java >6 - "org.osgi" % "org.osgi.core" % "4.2.0" % "provided", // The framework (Felix / Eclipse) provides the classes + "org.ops4j.pax.exam" % "pax-exam-container-native" % paxExamVersion, "org.ops4j.pax.exam" % "pax-exam-junit4" % paxExamVersion, "org.ops4j.pax.exam" % "pax-exam-link-assembly" % paxExamVersion, - "org.ops4j.pax.url" % "pax-url-aether" % "2.2.0", - "org.ops4j.pax.swissbox" % "pax-swissbox-tracker" % "1.8.0", - "ch.qos.logback" % "logback-core" % "1.1.2", - "ch.qos.logback" % "logback-classic" % "1.1.2", + "org.ops4j.pax.url" % "pax-url-aether" % "2.4.1", + "org.ops4j.pax.swissbox" % "pax-swissbox-tracker" % "1.8.1", + "ch.qos.logback" % "logback-core" % "1.1.3", + "ch.qos.logback" % "logback-classic" % "1.1.3", + "org.slf4j" % "slf4j-api" % "1.7.12", framework % "test" ) }, @@ -658,7 +657,7 @@ lazy val test = project // test sources are compiled in partest run, not here sources in IntegrationTest := Seq.empty, fork in IntegrationTest := true, - javaOptions in IntegrationTest += "-Xmx1G", + javaOptions in IntegrationTest += "-Xmx2G", testFrameworks += new TestFramework("scala.tools.partest.sbt.Framework"), testOptions in IntegrationTest += Tests.Argument("-Dpartest.java_opts=-Xmx1024M -Xms64M -XX:MaxPermSize=128M"), testOptions in IntegrationTest += Tests.Argument("-Dpartest.scalac_opts=" + (scalacOptions in Compile).value.mkString(" ")), diff --git a/project/ScriptCommands.scala b/project/ScriptCommands.scala index b6565803b49e..e5ff38617eab 100644 --- a/project/ScriptCommands.scala +++ b/project/ScriptCommands.scala @@ -25,6 +25,7 @@ object ScriptCommands { Project.extract(state).append(Seq( resolvers in Global += "scala-pr" at url, scalacOptions in Compile in ThisBuild += "-opt:l:classpath", + testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff")), logLevel in ThisBuild := Level.Info, logLevel in update in ThisBuild := Level.Warn ), state) From d45a9a6a70a8180987c4b65cd36107955d20ec8f Mon Sep 17 00:00:00 2001 From: Martin Olsson Date: Sun, 26 Jun 2016 00:22:08 +0200 Subject: [PATCH 109/153] Fix typo in test comment --- test/files/run/t3326.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/files/run/t3326.scala b/test/files/run/t3326.scala index 4ac7ef9138d8..b6b4eac784bb 100644 --- a/test/files/run/t3326.scala +++ b/test/files/run/t3326.scala @@ -19,7 +19,7 @@ import scala.math.Ordering * This is why `collection.SortedMap` used to resort to the generic * `TraversableLike.++` which knows nothing about the ordering. * - * To avoid `collection.SortedMap`s resort to the more generic `TraverableLike.++`, + * To avoid `collection.SortedMap`s resort to the more generic `TraversableLike.++`, * we override the `MapLike.++` overload in `collection.SortedMap` to return * the proper type `SortedMap`. */ From 22dac3118e97b2a4707d42ef1f47ac292a8ed385 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 14 Jun 2016 16:54:08 +0200 Subject: [PATCH 110/153] Temporarily insource Scalacheck 1.11.6 This is a temporary measure until we release Scala 2.12.0. It means we are able to release milestones, and RCs of Scala without needing a public release of Scalacheck. While we've never had to wait very long for these in the past (Thanks, Rickard!) we'd like to spare the maintainer some work betwen now and 2.12.0. After we release Scala 2.12.0, we'll revert to a binary dependency on the standard Scalacheck. I have replaced the scala-parser-combinator based command line option parsing with a quick and dirty version. I've had to remove scalacheck as a SBT test framework in our build. We don't use it directly as such (instead, it is used indirectly through `partest --scalacheck`), and it's test discovery (which we expect to return nothing) fails after re-STARR-ing due to an unsolved problem with SBT's testLoader including either STARR or sbt-launch.jar on the classpath used to discover and spawn tests. For the record, I tried the following to no avail: ``` // Two modifications are needed from the stock SBT configuration in order to exclude STARR // from the classloader that performs test discovery. // - We make `isManagedVersion` hold by providing an explicit Scala version, in order to go into the desired // branch in `createTestLoader` // - We remove STARR from the classloader of the scala instance def fixTestLoader = testLoader := { val s = scalaInstance.value val scalaInstance1 = new ScalaInstance(s.version, appConfiguration.value.provider.scalaProvider.loader(), s.libraryJar, s.compilerJar, s.extraJars, Some(s.actualVersion)) assert(scalaInstance1.isManagedVersion) TestFramework.createTestLoader(Attributed.data(fullClasspath.value), scalaInstance1, IO.createUniqueDirectory(taskTemporaryDirectory.value)) } ``` f --- build.sbt | 5 +- build.xml | 21 +- doc/LICENSE.md | 1 + doc/licenses/bsd_scalacheck.txt | 32 + .../scala/org/scalacheck/Arbitrary.scala | 433 ++++++++ .../scala/org/scalacheck/Commands.scala | 146 +++ .../scala/org/scalacheck/Commands2.scala | 150 +++ .../scala/org/scalacheck/Gen.scala | 813 +++++++++++++++ .../scala/org/scalacheck/Prop.scala | 953 ++++++++++++++++++ .../scala/org/scalacheck/Properties.scala | 82 ++ .../org/scalacheck/ScalaCheckFramework.scala | 93 ++ .../scala/org/scalacheck/Shrink.scala | 215 ++++ .../scala/org/scalacheck/Test.scala | 372 +++++++ .../scala/org/scalacheck/util/Buildable.scala | 77 ++ .../org/scalacheck/util/CmdLineParser.scala | 41 + .../org/scalacheck/util/ConsoleReporter.scala | 44 + .../scala/org/scalacheck/util/FreqMap.scala | 65 ++ .../scala/org/scalacheck/util/Pretty.scala | 129 +++ versions.properties | 4 +- 19 files changed, 3653 insertions(+), 23 deletions(-) create mode 100644 doc/licenses/bsd_scalacheck.txt create mode 100644 src/partest-extras/scala/org/scalacheck/Arbitrary.scala create mode 100644 src/partest-extras/scala/org/scalacheck/Commands.scala create mode 100644 src/partest-extras/scala/org/scalacheck/Commands2.scala create mode 100644 src/partest-extras/scala/org/scalacheck/Gen.scala create mode 100644 src/partest-extras/scala/org/scalacheck/Prop.scala create mode 100644 src/partest-extras/scala/org/scalacheck/Properties.scala create mode 100644 src/partest-extras/scala/org/scalacheck/ScalaCheckFramework.scala create mode 100644 src/partest-extras/scala/org/scalacheck/Shrink.scala create mode 100644 src/partest-extras/scala/org/scalacheck/Test.scala create mode 100644 src/partest-extras/scala/org/scalacheck/util/Buildable.scala create mode 100644 src/partest-extras/scala/org/scalacheck/util/CmdLineParser.scala create mode 100644 src/partest-extras/scala/org/scalacheck/util/ConsoleReporter.scala create mode 100644 src/partest-extras/scala/org/scalacheck/util/FreqMap.scala create mode 100644 src/partest-extras/scala/org/scalacheck/util/Pretty.scala diff --git a/build.sbt b/build.sbt index 20ae42b3e6b1..1d4e208da2e3 100644 --- a/build.sbt +++ b/build.sbt @@ -60,7 +60,6 @@ val scalaParserCombinatorsDep = scalaDep("org.scala-lang.modules", "scala-par val scalaSwingDep = scalaDep("org.scala-lang.modules", "scala-swing") val scalaXmlDep = scalaDep("org.scala-lang.modules", "scala-xml") val partestDep = scalaDep("org.scala-lang.modules", "scala-partest", versionProp = "partest") -val scalacheckDep = scalaDep("org.scalacheck", "scalacheck", scope = "it") // Non-Scala dependencies: val junitDep = "junit" % "junit" % "4.11" @@ -562,6 +561,7 @@ lazy val junit = project.in(file("test") / "junit") fork in Test := true, libraryDependencies ++= Seq(junitDep, junitInterfaceDep, jolDep), testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"), + testFrameworks -= new TestFramework("org.scalacheck.ScalaCheckFramework"), unmanagedSourceDirectories in Test := List(baseDirectory.value) ) @@ -642,7 +642,7 @@ lazy val test = project .settings(disablePublishing: _*) .settings(Defaults.itSettings: _*) .settings( - libraryDependencies ++= Seq(asmDep, partestDep, scalaXmlDep, scalacheckDep), + libraryDependencies ++= Seq(asmDep, partestDep, scalaXmlDep), libraryDependencies ++= { // Resolve the JARs for all test/files/lib/*.jar.desired.sha1 files through Ivy val baseDir = (baseDirectory in ThisBuild).value @@ -659,6 +659,7 @@ lazy val test = project fork in IntegrationTest := true, javaOptions in IntegrationTest += "-Xmx2G", testFrameworks += new TestFramework("scala.tools.partest.sbt.Framework"), + testFrameworks -= new TestFramework("org.scalacheck.ScalaCheckFramework"), testOptions in IntegrationTest += Tests.Argument("-Dpartest.java_opts=-Xmx1024M -Xms64M -XX:MaxPermSize=128M"), testOptions in IntegrationTest += Tests.Argument("-Dpartest.scalac_opts=" + (scalacOptions in Compile).value.mkString(" ")), testOptions in IntegrationTest += Tests.Setup { () => diff --git a/build.xml b/build.xml index 519d3597cc6c..6b2c9ade0da4 100644 --- a/build.xml +++ b/build.xml @@ -319,7 +319,6 @@ TODO: - @@ -339,11 +338,6 @@ TODO: - - - - - @@ -567,7 +561,6 @@ TODO: - @@ -577,7 +570,6 @@ TODO: - @@ -922,7 +914,7 @@ TODO: (but not scala-library, so we filter that one out...) so we provide them: scala-[library/reflect/compiler], scalap built here, scala-xml, scala-parser-combinators via external-modules-nocore, - scalacheck as part of `partest.classpath` --> + as part of `partest.classpath` --> @@ -933,17 +925,6 @@ TODO: - - - - - - - - - - - diff --git a/doc/LICENSE.md b/doc/LICENSE.md index a07ba32e0b07..0718c43e05df 100644 --- a/doc/LICENSE.md +++ b/doc/LICENSE.md @@ -46,6 +46,7 @@ This license is used by the following third-party libraries: This license is used by the following third-party libraries: * jline + * scalacheck ### [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) This license is used by the following third-party libraries: diff --git a/doc/licenses/bsd_scalacheck.txt b/doc/licenses/bsd_scalacheck.txt new file mode 100644 index 000000000000..f1920752e0f6 --- /dev/null +++ b/doc/licenses/bsd_scalacheck.txt @@ -0,0 +1,32 @@ +ScalaCheck LICENSE + +Copyright (c) 2007-2013, Rickard Nilsson +All rights reserved. + +Permission to use, copy, modify, and distribute this software in source +or binary form for any purpose with or without fee is hereby granted, +provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the author nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/src/partest-extras/scala/org/scalacheck/Arbitrary.scala b/src/partest-extras/scala/org/scalacheck/Arbitrary.scala new file mode 100644 index 000000000000..1cbd668f0c34 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/Arbitrary.scala @@ -0,0 +1,433 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +import util.{FreqMap, Buildable, Buildable2} + + +sealed abstract class Arbitrary[T] { + val arbitrary: Gen[T] +} + +/** Defines implicit [[org.scalacheck.Arbitrary]] instances for common types. + *

+ * ScalaCheck + * uses implicit [[org.scalacheck.Arbitrary]] instances when creating properties + * out of functions with the `Prop.property` method, and when + * the `Arbitrary.arbitrary` method is used. For example, the + * following code requires that there exists an implicit + * `Arbitrary[MyClass]` instance: + *

+ * + * {{{ + * val myProp = Prop.forAll { myClass: MyClass => + * ... + * } + * + * val myGen = Arbitrary.arbitrary[MyClass] + * }}} + * + *

+ * The required implicit definition could look like this: + *

+ * + * {{{ + * implicit val arbMyClass: Arbitrary[MyClass] = Arbitrary(...) + * }}} + * + *

+ * The factory method `Arbitrary(...)` takes a generator of type + * `Gen[T]` and returns an instance of `Arbitrary[T]`. + *

+ * + *

+ * The `Arbitrary` module defines implicit [[org.scalacheck.Arbitrary]] + * instances for common types, for convenient use in your properties and + * generators. + *

+ */ +object Arbitrary { + + import Gen.{const, choose, sized, frequency, oneOf, containerOf, resize} + import collection.{immutable, mutable} + import java.util.Date + + /** Creates an Arbitrary instance */ + def apply[T](g: => Gen[T]): Arbitrary[T] = new Arbitrary[T] { + lazy val arbitrary = g + } + + /** Returns an arbitrary generator for the type T. */ + def arbitrary[T](implicit a: Arbitrary[T]): Gen[T] = a.arbitrary + + /**** Arbitrary instances for each AnyVal ****/ + + /** Arbitrary AnyVal */ + implicit lazy val arbAnyVal: Arbitrary[AnyVal] = Arbitrary(oneOf( + arbitrary[Unit], arbitrary[Boolean], arbitrary[Char], arbitrary[Byte], + arbitrary[Short], arbitrary[Int], arbitrary[Long], arbitrary[Float], + arbitrary[Double] + )) + + /** Arbitrary instance of Boolean */ + implicit lazy val arbBool: Arbitrary[Boolean] = + Arbitrary(oneOf(true, false)) + + /** Arbitrary instance of Int */ + implicit lazy val arbInt: Arbitrary[Int] = Arbitrary( + Gen.chooseNum(Int.MinValue, Int.MaxValue) + ) + + /** Arbitrary instance of Long */ + implicit lazy val arbLong: Arbitrary[Long] = Arbitrary( + Gen.chooseNum(Long.MinValue, Long.MaxValue) + ) + + /** Arbitrary instance of Float */ + implicit lazy val arbFloat: Arbitrary[Float] = Arbitrary( + Gen.chooseNum( + Float.MinValue, Float.MaxValue + // I find that including these by default is a little TOO testy. + // Float.Epsilon, Float.NaN, Float.PositiveInfinity, Float.NegativeInfinity + ) + ) + + /** Arbitrary instance of Double */ + implicit lazy val arbDouble: Arbitrary[Double] = Arbitrary( + Gen.chooseNum( + Double.MinValue / 2, Double.MaxValue / 2 + // As above. Perhaps behind some option? + // Double.Epsilon, Double.NaN, Double.PositiveInfinity, Double.NegativeInfinity + ) + ) + + /** Arbitrary instance of Char */ + implicit lazy val arbChar: Arbitrary[Char] = Arbitrary( + Gen.frequency( + (0xD800-Char.MinValue, Gen.choose[Char](Char.MinValue,0xD800-1)), + (Char.MaxValue-0xDFFF, Gen.choose[Char](0xDFFF+1,Char.MaxValue)) + ) + ) + + /** Arbitrary instance of Byte */ + implicit lazy val arbByte: Arbitrary[Byte] = Arbitrary( + Gen.chooseNum(Byte.MinValue, Byte.MaxValue) + ) + + /** Arbitrary instance of Short */ + implicit lazy val arbShort: Arbitrary[Short] = Arbitrary( + Gen.chooseNum(Short.MinValue, Short.MaxValue) + ) + + /** Absolutely, totally, 100% arbitrarily chosen Unit. */ + implicit lazy val arbUnit: Arbitrary[Unit] = Arbitrary(const(())) + + /**** Arbitrary instances of other common types ****/ + + /** Arbitrary instance of String */ + implicit lazy val arbString: Arbitrary[String] = + Arbitrary(arbitrary[List[Char]] map (_.mkString)) + + /** Arbitrary instance of Date */ + implicit lazy val arbDate: Arbitrary[Date] = Arbitrary(for { + l <- arbitrary[Long] + d = new Date + } yield new Date(d.getTime + l)) + + /** Arbitrary instance of Throwable */ + implicit lazy val arbThrowable: Arbitrary[Throwable] = + Arbitrary(oneOf(const(new Exception), const(new Error))) + + /** Arbitrary instance of Exception */ + implicit lazy val arbException: Arbitrary[Exception] = + Arbitrary(const(new Exception)) + + /** Arbitrary instance of Error */ + implicit lazy val arbError: Arbitrary[Error] = + Arbitrary(const(new Error)) + + /** Arbitrary BigInt */ + implicit lazy val arbBigInt: Arbitrary[BigInt] = { + def chooseBigInt: Gen[BigInt] = + sized((s: Int) => choose(-s, s)) map (x => BigInt(x)) + + def chooseReallyBigInt: Gen[BigInt] = for { + bi <- chooseBigInt + n <- choose(32,128) + } yield bi << n + + Arbitrary( + frequency( + (5, chooseBigInt), + (10, chooseReallyBigInt), + (1, BigInt(0)), + (1, BigInt(1)), + (1, BigInt(-1)), + (1, BigInt(Int.MaxValue) + 1), + (1, BigInt(Int.MinValue) - 1), + (1, BigInt(Long.MaxValue)), + (1, BigInt(Long.MinValue)), + (1, BigInt(Long.MaxValue) + 1), + (1, BigInt(Long.MinValue) - 1) + ) + ) + } + + /** Arbitrary BigDecimal */ + implicit lazy val arbBigDecimal: Arbitrary[BigDecimal] = { + import java.math.MathContext._ + val mcGen = oneOf(UNLIMITED, DECIMAL32, DECIMAL64, DECIMAL128) + val bdGen = for { + x <- arbBigInt.arbitrary + mc <- mcGen + limit <- const(if(mc == UNLIMITED) 0 else math.max(x.abs.toString.length - mc.getPrecision, 0)) + scale <- Gen.chooseNum(Int.MinValue + limit , Int.MaxValue) + } yield { + try { + BigDecimal(x, scale, mc) + } catch { + case ae: java.lang.ArithmeticException => BigDecimal(x, scale, UNLIMITED) // Handle the case where scale/precision conflict + } + } + Arbitrary(bdGen) + } + + /** Arbitrary java.lang.Number */ + implicit lazy val arbNumber: Arbitrary[Number] = { + val gen = Gen.oneOf( + arbitrary[Byte], arbitrary[Short], arbitrary[Int], arbitrary[Long], + arbitrary[Float], arbitrary[Double] + ) + Arbitrary(gen map (_.asInstanceOf[Number])) + // XXX TODO - restore BigInt and BigDecimal + // Arbitrary(oneOf(arbBigInt.arbitrary :: (arbs map (_.arbitrary) map toNumber) : _*)) + } + + /** Generates an arbitrary property */ + implicit lazy val arbProp: Arbitrary[Prop] = { + import Prop._ + val undecidedOrPassed = forAll { b: Boolean => + b ==> true + } + Arbitrary(frequency( + (4, falsified), + (4, passed), + (3, proved), + (3, undecidedOrPassed), + (2, undecided), + (1, exception(null)) + )) + } + + /** Arbitrary instance of test parameters */ + implicit lazy val arbTestParameters: Arbitrary[Test.Parameters] = + Arbitrary(for { + _minSuccTests <- choose(10,200) + _maxDiscardRatio <- choose(0.2f,10f) + _minSize <- choose(0,500) + sizeDiff <- choose(0,500) + _maxSize <- choose(_minSize, _minSize + sizeDiff) + _workers <- choose(1,4) + } yield new Test.Parameters.Default { + override val minSuccessfulTests = _minSuccTests + override val maxDiscardRatio = _maxDiscardRatio + override val minSize = _minSize + override val maxSize = _maxSize + override val workers = _workers + }) + + /** Arbitrary instance of gen params */ + implicit lazy val arbGenParams: Arbitrary[Gen.Parameters] = + Arbitrary(for { + sz <- arbitrary[Int] suchThat (_ >= 0) + } yield (new Gen.Parameters.Default { + override val size = sz + })) + + + // Higher-order types // + + /** Arbitrary instance of [[org.scalacheck.Gen]] */ + implicit def arbGen[T](implicit a: Arbitrary[T]): Arbitrary[Gen[T]] = + Arbitrary(frequency( + (5, arbitrary[T] map (const(_))), + (1, Gen.fail) + )) + + /** Arbitrary instance of the Option type */ + implicit def arbOption[T](implicit a: Arbitrary[T]): Arbitrary[Option[T]] = + Arbitrary(sized(n => + // When n is larger, make it less likely that we generate None, + // but still do it some of the time. When n is zero, we always + // generate None, since it's the smallest value. + frequency( + (n, resize(n / 2, arbitrary[T]).map(Some(_))), + (1, const(None))))) + + /** Arbitrary instance of the Either type */ + implicit def arbEither[T, U](implicit at: Arbitrary[T], au: Arbitrary[U]): Arbitrary[Either[T, U]] = + Arbitrary(oneOf(arbitrary[T].map(Left(_)), arbitrary[U].map(Right(_)))) + + /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container + * (such as lists, arrays, streams, etc). The maximum size of the container + * depends on the size generation parameter. */ + implicit def arbContainer[C[_],T](implicit + a: Arbitrary[T], b: Buildable[T,C], t: C[T] => Traversable[T] + ): Arbitrary[C[T]] = Arbitrary(containerOf[C,T](arbitrary[T])) + + /** Arbitrary instance of any [[org.scalacheck.util.Buildable2]] container + * (such as maps, etc). The maximum size of the container depends on the size + * generation parameter. */ + implicit def arbContainer2[C[_,_],T,U](implicit + a: Arbitrary[(T,U)], b: Buildable2[T,U,C], t: C[T,U] => Traversable[(T,U)] + ): Arbitrary[C[T,U]] = Arbitrary(containerOf[C,T,U](arbitrary[(T,U)])) + + // Functions // + + /** Arbitrary instance of Function1 */ + implicit def arbFunction1[T1,R](implicit a: Arbitrary[R] + ): Arbitrary[T1 => R] = Arbitrary( + for(r <- arbitrary[R]) yield (t1: T1) => r + ) + + /** Arbitrary instance of Function2 */ + implicit def arbFunction2[T1,T2,R](implicit a: Arbitrary[R] + ): Arbitrary[(T1,T2) => R] = Arbitrary( + for(r <- arbitrary[R]) yield (t1: T1, t2: T2) => r + ) + + /** Arbitrary instance of Function3 */ + implicit def arbFunction3[T1,T2,T3,R](implicit a: Arbitrary[R] + ): Arbitrary[(T1,T2,T3) => R] = Arbitrary( + for(r <- arbitrary[R]) yield (t1: T1, t2: T2, t3: T3) => r + ) + + /** Arbitrary instance of Function4 */ + implicit def arbFunction4[T1,T2,T3,T4,R](implicit a: Arbitrary[R] + ): Arbitrary[(T1,T2,T3,T4) => R] = Arbitrary( + for(r <- arbitrary[R]) yield (t1: T1, t2: T2, t3: T3, t4: T4) => r + ) + + /** Arbitrary instance of Function5 */ + implicit def arbFunction5[T1,T2,T3,T4,T5,R](implicit a: Arbitrary[R] + ): Arbitrary[(T1,T2,T3,T4,T5) => R] = Arbitrary( + for(r <- arbitrary[R]) yield (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => r + ) + + + // Tuples // + + /** Arbitrary instance of 2-tuple */ + implicit def arbTuple2[T1,T2](implicit + a1: Arbitrary[T1], a2: Arbitrary[T2] + ): Arbitrary[(T1,T2)] = + Arbitrary(for { + t1 <- arbitrary[T1] + t2 <- arbitrary[T2] + } yield (t1,t2)) + + /** Arbitrary instance of 3-tuple */ + implicit def arbTuple3[T1,T2,T3](implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3] + ): Arbitrary[(T1,T2,T3)] = + Arbitrary(for { + t1 <- arbitrary[T1] + t2 <- arbitrary[T2] + t3 <- arbitrary[T3] + } yield (t1,t2,t3)) + + /** Arbitrary instance of 4-tuple */ + implicit def arbTuple4[T1,T2,T3,T4](implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4] + ): Arbitrary[(T1,T2,T3,T4)] = + Arbitrary(for { + t1 <- arbitrary[T1] + t2 <- arbitrary[T2] + t3 <- arbitrary[T3] + t4 <- arbitrary[T4] + } yield (t1,t2,t3,t4)) + + /** Arbitrary instance of 5-tuple */ + implicit def arbTuple5[T1,T2,T3,T4,T5](implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4], + a5: Arbitrary[T5] + ): Arbitrary[(T1,T2,T3,T4,T5)] = + Arbitrary(for { + t1 <- arbitrary[T1] + t2 <- arbitrary[T2] + t3 <- arbitrary[T3] + t4 <- arbitrary[T4] + t5 <- arbitrary[T5] + } yield (t1,t2,t3,t4,t5)) + + /** Arbitrary instance of 6-tuple */ + implicit def arbTuple6[T1,T2,T3,T4,T5,T6](implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4], + a5: Arbitrary[T5], a6: Arbitrary[T6] + ): Arbitrary[(T1,T2,T3,T4,T5,T6)] = + Arbitrary(for { + t1 <- arbitrary[T1] + t2 <- arbitrary[T2] + t3 <- arbitrary[T3] + t4 <- arbitrary[T4] + t5 <- arbitrary[T5] + t6 <- arbitrary[T6] + } yield (t1,t2,t3,t4,t5,t6)) + + /** Arbitrary instance of 7-tuple */ + implicit def arbTuple7[T1,T2,T3,T4,T5,T6,T7](implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4], + a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7] + ): Arbitrary[(T1,T2,T3,T4,T5,T6,T7)] = + Arbitrary(for { + t1 <- arbitrary[T1] + t2 <- arbitrary[T2] + t3 <- arbitrary[T3] + t4 <- arbitrary[T4] + t5 <- arbitrary[T5] + t6 <- arbitrary[T6] + t7 <- arbitrary[T7] + } yield (t1,t2,t3,t4,t5,t6,t7)) + + /** Arbitrary instance of 8-tuple */ + implicit def arbTuple8[T1,T2,T3,T4,T5,T6,T7,T8](implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4], + a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7], a8: Arbitrary[T8] + ): Arbitrary[(T1,T2,T3,T4,T5,T6,T7,T8)] = + Arbitrary(for { + t1 <- arbitrary[T1] + t2 <- arbitrary[T2] + t3 <- arbitrary[T3] + t4 <- arbitrary[T4] + t5 <- arbitrary[T5] + t6 <- arbitrary[T6] + t7 <- arbitrary[T7] + t8 <- arbitrary[T8] + } yield (t1,t2,t3,t4,t5,t6,t7,t8)) + + /** Arbitrary instance of 9-tuple */ + implicit def arbTuple9[T1,T2,T3,T4,T5,T6,T7,T8,T9](implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4], + a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7], a8: Arbitrary[T8], + a9: Arbitrary[T9] + ): Arbitrary[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] = + Arbitrary(for { + t1 <- arbitrary[T1] + t2 <- arbitrary[T2] + t3 <- arbitrary[T3] + t4 <- arbitrary[T4] + t5 <- arbitrary[T5] + t6 <- arbitrary[T6] + t7 <- arbitrary[T7] + t8 <- arbitrary[T8] + t9 <- arbitrary[T9] + } yield (t1,t2,t3,t4,t5,t6,t7,t8,t9)) + +} diff --git a/src/partest-extras/scala/org/scalacheck/Commands.scala b/src/partest-extras/scala/org/scalacheck/Commands.scala new file mode 100644 index 000000000000..5ff3a397e557 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/Commands.scala @@ -0,0 +1,146 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +/** See User Guide for usage examples */ +@deprecated("Will be replaced with a new implementation in 1.12.0", "1.11.4") +trait Commands extends Prop { + + /** The abstract state data type. This type must be immutable. + * The state type that encodes the abstract state. The abstract state + * should model all the features we need from the real state, the system + * under test. We should leave out all details that aren't needed for + * specifying our pre- and postconditions. The state type must be called + * State and be immutable. */ + type State <: AnyRef + + class Binding(private val key: State) { + def get: Any = bindings.find(_._1 eq key) match { + case None => sys.error("No value bound") + case Some(x) => x._2 + } + } + + /** Abstract commands are defined as subtypes of the traits Command or SetCommand. + * Each command must have a run method and a method that returns the new abstract + * state, as it should look after the command has been run. + * A command can also define a precondition that states how the current + * abstract state must look if the command should be allowed to run. + * Finally, we can also define a postcondition which verifies that the + * system under test is in a correct state after the command exectution. */ + trait Command { + + /** Used internally. */ + protected[Commands] def run_(s: State) = run(s) + + def run(s: State): Any + def nextState(s: State): State + + /** Returns all preconditions merged into a single function */ + def preCondition: (State => Boolean) = + s => preConditions.toList.forall(_.apply(s)) + + /** A precondition is a function that + * takes the current abstract state as parameter and returns a boolean + * that says if the precondition is fulfilled or not. You can add several + * conditions to the precondition list */ + val preConditions = new collection.mutable.ListBuffer[State => Boolean] + + /** Returns all postconditions merged into a single function */ + def postCondition: (State,State,Any) => Prop = + (s0,s1,r) => Prop.all(postConditions.map(_.apply(s0,s1,r)): _*) + + /** A postcondition is a function that + * takes three parameters, s0, s1 and r. s0 is the abstract state before + * the command was run, s1 is the abstract state after the command was + * run, and r is the result from the command's run + * method. The postcondition function should return a Boolean (or + * a Prop instance) that says if the condition holds or not. You can add several + * conditions to the postConditions list. */ + val postConditions = new collection.mutable.ListBuffer[(State,State,Any) => Prop] + } + + /** A command that binds its result for later use */ + trait SetCommand extends Command { + /** Used internally. */ + protected[Commands] final override def run_(s: State) = { + val r = run(s) + bindings += ((s,r)) + r + } + + final def nextState(s: State) = nextState(s, new Binding(s)) + def nextState(s: State, b: Binding): State + } + + private case class Cmds(cs: List[Command], ss: List[State]) { + override def toString = cs.map(_.toString).mkString(", ") + } + + private val bindings = new scala.collection.mutable.ListBuffer[(State,Any)] + + private def initState() = { + bindings.clear() + initialState() + } + + private def genCmds: Gen[Cmds] = { + def sizedCmds(s: State, sz: Int): Gen[Cmds] = { + if(sz <= 0) Gen.const(Cmds(Nil, Nil)) else for { + c <- genCommand(s) suchThat (_.preCondition(s)) + Cmds(cs,ss) <- sizedCmds(c.nextState(s), sz-1) + } yield Cmds(c::cs, s::ss) + } + + Gen.sized(sz => sizedCmds(initialState(), sz)) + } + + private def validCmds(s: State, cs: List[Command]): Option[Cmds] = + cs match { + case Nil => Some(Cmds(Nil, s::Nil)) + case c::_ if !c.preCondition(s) => None + case c::cmds => for { + Cmds(_, ss) <- validCmds(c.nextState(s), cmds) + } yield Cmds(cs, s::ss) + } + + private def runCommands(cmds: Cmds): Prop = Prop.all { + cmds.cs.indices.map { i => + val (c,s) = (cmds.cs(i), cmds.ss(i)) + c.postCondition(s,c.nextState(s),c.run_(s)) + } : _* + } + + private def commandsProp: Prop = { + def shrinkCmds(cmds: Cmds) = + Shrink.shrink(cmds.cs)(Shrink.shrinkContainer).flatMap { cs => + validCmds(initialState(), cs).toList + } + + Prop.forAllShrink(genCmds label "COMMANDS", shrinkCmds)(runCommands _) + } + + def apply(p: Gen.Parameters) = commandsProp(p) + + /** initialState should reset the system under test to a well defined + * initial state, and return the abstract version of that state. */ + def initialState(): State + + /** The command generator. Given an abstract state, the generator + * should return a command that is allowed to run in that state. Note that + * it is still neccessary to define preconditions on the commands if there + * are any. The generator is just giving a hint of which commands that are + * suitable for a given state, the preconditions will still be checked before + * a command runs. Sometimes you maybe want to adjust the distribution of + * your command generator according to the state, or do other calculations + * based on the state. */ + def genCommand(s: State): Gen[Command] + +} diff --git a/src/partest-extras/scala/org/scalacheck/Commands2.scala b/src/partest-extras/scala/org/scalacheck/Commands2.scala new file mode 100644 index 000000000000..67393a7a7055 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/Commands2.scala @@ -0,0 +1,150 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +private[scalacheck] trait Commands2 { + + /** The abstract state type. Must be immutable. + * The [[Commands2.State]] type should model the state of the system under test (SUT). + * It should leave out all details that aren't needed for specifying our + * pre- and postconditions. */ + type State + + /** A type representing one instance of the system under test (SUT). + * The [[Commands2.System]] type should be a proxy to the actual system under test. + * It is used in the postconditions to verify that the real system + * behaves according to specification. It should be possible to have + * up to [[Commands2.maxSystemInstanceCount]] co-existing instances of the System + * type, and each System instance should be a proxy to a distinct + * SUT instance. There should be no dependencies between the System + * instances, as they might be used in parallel by ScalaCheck. + * System instances are created by [[Commands2.newSystemInstance]] and destroyed by + * [[Commands2.destroySystemInstance]]. [[Commands2.newSystemInstance]] and + * [[Commands2.destroySystemInstance]] might be called at any time by ScalaCheck, + * as long as [[Commands2.maxSystemInstanceCount]] isn't violated. */ + type System + + /** The maximum number of concurrent [[Commands2.System]] instances allowed to exist. */ + def maxSystemInstanceCount: Int + + /** Should create a new [[Commands2.System]] instance with an internal state that + * corresponds to the provided abstract state instance. The provided state + * is guaranteed to fulfill [[Commands2.initialPreCondition]], and + * [[Commands2.newSystemInstance]] will never be called if there already + * is [[Commands2.maxSystemInstanceCount]] instances of [[Commands2.System]] */ + def newSystemInstance(state: State): System + + /** Should destroy the given SUT, so that a new [[Commands2.System]] instance can be + * created with [[Commands2.newSystemInstance]]. */ + def destroySystemInstance(system: System): Unit + + /** The precondition for the initial state, when no commands yet have + * run. This is used by ScalaCheck when command sequences are shrinked + * and the first state might differ from what is returned from + * [[Commands2.initialState]]. */ + def initialPreCondition(state: State): Boolean + + /** A generator that should produce an initial [[Commands2.State]] instance that is + * usable by [[Commands2.newSystemInstance]] to create a new system under test. + * The state returned by this generator is always checked with the + * [[Commands2.initialPreCondition]] method before it is used. */ + def genInitialState: Gen[State] + + /** A generator that, given the current abstract state, should produce + * a suitable Command instance. */ + def genCommand(state: State): Gen[Command] + + /** Abstract commands are defined as subtypes of the trait [[Commands2.Command]]. + * Each command must have a run method and a method + * that returns the new abstract state, as it is supposed to look after + * the command has been run. A command can also define a precondition + * that defines how the current abstract state must look if the command + * should be allowed to run. Finally, you can also define a postcondition + * that verifies that the system under test is in a correct state after + * the command execution. */ + trait Command { + /** Runs this command in the system under test, + * represented by the provided [[Commands2.System]] instance. This method + * can return any value as result. The returned value will be + * used by the postcondition to decide if the system behaves as + * expected. */ + def run(state: State, system: System): Any + + /** Returns a new abstract [[Commands2.State]] instance that represents the + * state of the system after this command has run. */ + def nextState(state: State): State + + /** The precondition that decides if this command is allowed to run + * when the system under test is in the specified (abstract) state. */ + def preCondition(state: State): Boolean + + /** The postcondition that decides if the system under test behaved + * correctly when the command ran. + * @param s0 The abstract state as it looked before this command ran. + * @param s1 The abstract state as it looked after this command ran. + * @param system The proxy for the system under test. The postcondition + * can query the system for its current state, but care must be taken + * not to mutate the system under test in any way. + * @param result The result returned from the [[Command.run]] method. + */ + def postCondition(s0: State, s1: State, system: System, result: Any): Prop + } + +/* WIP + private case class Cmds(cs: List[Command], ss: List[State]) { + override def toString = cs.map(_.toString).mkString(", ") + } + + private val bindings = new scala.collection.mutable.ListBuffer[(State,Any)] + + private def initState() = { + bindings.clear() + initialState() + } + + private def genCmds: Gen[Cmds] = { + def sizedCmds(s: State, sz: Int): Gen[Cmds] = { + if(sz <= 0) Gen.const(Cmds(Nil, Nil)) else for { + c <- genCommand(s) suchThat (_.preCondition(s)) + Cmds(cs,ss) <- sizedCmds(c.nextState(s), sz-1) + } yield Cmds(c::cs, s::ss) + } + + Gen.sized(sz => sizedCmds(initialState(), sz)) + } + + private def validCmds(s: State, cs: List[Command]): Option[Cmds] = + cs match { + case Nil => Some(Cmds(Nil, s::Nil)) + case c::_ if !c.preCondition(s) => None + case c::cmds => for { + Cmds(_, ss) <- validCmds(c.nextState(s), cmds) + } yield Cmds(cs, s::ss) + } + + private def runCommands(cmds: Cmds): Prop = Prop.all { + cmds.cs.indices.map { i => + val (c,s) = (cmds.cs(i), cmds.ss(i)) + c.postCondition(s,c.nextState(s),c.run_(s)) + } : _* + } + + private def commandsProp: Prop = { + def shrinkCmds(cmds: Cmds) = + Shrink.shrink(cmds.cs)(Shrink.shrinkContainer).flatMap { cs => + validCmds(initialState(), cs).toList + } + + Prop.forAllShrink(genCmds label "COMMANDS", shrinkCmds)(runCommands _) + } + + def apply(p: Prop.Params) = commandsProp(p) +*/ +} diff --git a/src/partest-extras/scala/org/scalacheck/Gen.scala b/src/partest-extras/scala/org/scalacheck/Gen.scala new file mode 100644 index 000000000000..ba82c9ea95d5 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/Gen.scala @@ -0,0 +1,813 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +import util.{Buildable, Buildable2} +import scala.collection.immutable.TreeMap + +sealed trait Gen[+T] { + + //// Private interface //// + + import Gen.{R, r, gen} + + /** Just an alias */ + private type P = Gen.Parameters + + /** Should be a copy of R.sieve. Used internally in Gen when some generators + * with suchThat-claues are created (when R is not available). This method + * actually breaks covariance, but since this method will only ever be + * called with a value of exactly type T, it is OK. */ + protected def sieveCopy(x: Any): Boolean = true + + private[scalacheck] def doApply(p: P): R[T] + + + //// Public interface //// + + /** A class supporting filtered operations. */ + final class WithFilter(p: T => Boolean) { + def map[U](f: T => U): Gen[U] = Gen.this.suchThat(p).map(f) + def flatMap[U](f: T => Gen[U]): Gen[U] = Gen.this.suchThat(p).flatMap(f) + def withFilter(q: T => Boolean): WithFilter = Gen.this.withFilter(x => p(x) && q(x)) + } + + /** Evaluate this generator with the given parameters */ + def apply(p: Gen.Parameters): Option[T] = doApply(p).retrieve + + /** Create a new generator by mapping the result of this generator */ + def map[U](f: T => U): Gen[U] = gen { p => doApply(p).map(f) } + + /** Create a new generator by flat-mapping the result of this generator */ + def flatMap[U](f: T => Gen[U]): Gen[U] = gen { p => + doApply(p).flatMap(t => f(t).doApply(p)) + } + + /** Create a new generator that uses this generator to produce a value + * that fulfills the given condition. If the condition is not fulfilled, + * the generator fails (returns None). */ + def filter(p: T => Boolean): Gen[T] = suchThat(p) + + /** Creates a non-strict filtered version of this generator. */ + def withFilter(p: T => Boolean): WithFilter = new WithFilter(p) + + /** Create a new generator that uses this generator to produce a value + * that fulfills the given condition. If the condition is not fulfilled, + * the generator fails (returns None). This method is identical to + * [Gen.filter]. */ + def suchThat(f: T => Boolean): Gen[T] = new Gen[T] { + def doApply(p: P) = { + val res = Gen.this.doApply(p) + res.copy(s = { x:T => res.sieve(x) && f(x) }) + } + override def sieveCopy(x: Any) = + try Gen.this.sieveCopy(x) && f(x.asInstanceOf[T]) + catch { case _: java.lang.ClassCastException => false } + } + + /** Create a generator that calls this generator repeatedly until + * the given condition is fulfilled. The generated value is then + * returned. Use this combinator with care, since it may result + * in infinite loops. */ + def retryUntil(p: T => Boolean): Gen[T] = flatMap { t => + if (p(t)) Gen.const(t).suchThat(p) else retryUntil(p) + } + + def sample: Option[T] = doApply(Gen.Parameters.default).retrieve + + /** Returns a new property that holds if and only if both this + * and the given generator generates the same result, or both + * generators generate no result. */ + def ==[U](g: Gen[U]) = Prop { prms => + (doApply(prms).retrieve, g.doApply(prms).retrieve) match { + case (None,None) => Prop.proved(prms) + case (Some(r1),Some(r2)) if r1 == r2 => Prop.proved(prms) + case _ => Prop.falsified(prms) + } + } + + def !=[U](g: Gen[U]) = Prop.forAll(this)(r => Prop.forAll(g)(_ != r)) + + def !==[U](g: Gen[U]) = Prop { prms => + (doApply(prms).retrieve, g.doApply(prms).retrieve) match { + case (None,None) => Prop.falsified(prms) + case (Some(r1),Some(r2)) if r1 == r2 => Prop.falsified(prms) + case _ => Prop.proved(prms) + } + } + + /** Put a label on the generator to make test reports clearer */ + def label(l: String) = new Gen[T] { + def doApply(p: P) = { + val r = Gen.this.doApply(p) + r.copy(l = r.labels + l) + } + override def sieveCopy(x: Any) = Gen.this.sieveCopy(x) + } + + /** Put a label on the generator to make test reports clearer */ + def :|(l: String) = label(l) + + /** Put a label on the generator to make test reports clearer */ + def |:(l: String) = label(l) + + /** Put a label on the generator to make test reports clearer */ + def :|(l: Symbol) = label(l.toString.drop(1)) + + /** Put a label on the generator to make test reports clearer */ + def |:(l: Symbol) = label(l.toString.drop(1)) + +} + +object Gen { + + //// Private interface //// + + import Arbitrary.arbitrary + + /** Just an alias */ + private type P = Parameters + + private[scalacheck] trait R[+T] { + def labels: Set[String] = Set() + def sieve[U >: T]: U => Boolean = _ => true + protected def result: Option[T] + + def retrieve = result.filter(sieve) + + def copy[U >: T]( + l: Set[String] = this.labels, + s: U => Boolean = this.sieve, + r: Option[U] = this.result + ): R[U] = new R[U] { + override val labels = l + override def sieve[V >: U] = { x:Any => + try s(x.asInstanceOf[U]) + catch { case _: java.lang.ClassCastException => false } + } + val result = r + } + + def map[U](f: T => U): R[U] = r(retrieve.map(f)).copy(l = labels) + + def flatMap[U](f: T => R[U]): R[U] = retrieve match { + case None => r(None).copy(l = labels) + case Some(t) => + val r = f(t) + r.copy(l = labels ++ r.labels) + } + } + + private[scalacheck] def r[T](r: Option[T]): R[T] = new R[T] { + val result = r + } + + /** Generator factory method */ + private[scalacheck] def gen[T](f: P => R[T]): Gen[T] = new Gen[T] { + def doApply(p: P) = f(p) + } + + //// Public interface //// + + /** Generator parameters, used by [[org.scalacheck.Gen.apply]] */ + trait Parameters { + + /** The size of the generated value. Generator implementations are allowed + * to freely interpret (or ignore) this value. During test execution, the + * value of this parameter is controlled by [[Test.Parameters.minSize]] and + * [[Test.Parameters.maxSize]]. */ + val size: Int + + /** Create a copy of this [[Gen.Parameters]] instance with + * [[Gen.Parameters.size]] set to the specified value. */ + def withSize(size: Int): Parameters = cp(size = size) + + /** The random number generator used. */ + val rng: scala.util.Random + + /** Create a copy of this [[Gen.Parameters]] instance with + * [[Gen.Parameters.rng]] set to the specified value. */ + def withRng(rng: scala.util.Random): Parameters = cp(rng = rng) + + /** Change the size parameter. + * @deprecated Use [[Gen.Parameters.withSize]] instead. */ + @deprecated("Use withSize instead.", "1.11.2") + def resize(newSize: Int): Parameters = withSize(newSize) + + // private since we can't guarantee binary compatibility for this one + private case class cp( + size: Int = size, + rng: scala.util.Random = rng + ) extends Parameters + } + + /** Provides methods for creating [[org.scalacheck.Gen.Parameters]] values */ + object Parameters { + /** Default generator parameters trait. This can be overriden if you + * need to tweak the parameters. */ + trait Default extends Parameters { + val size: Int = 100 + val rng: scala.util.Random = scala.util.Random + } + + /** Default generator parameters instance. */ + val default: Parameters = new Default {} + } + + /** A wrapper type for range types */ + trait Choose[T] { + /** Creates a generator that returns a value in the given inclusive range */ + def choose(min: T, max: T): Gen[T] + } + + /** Provides implicit [[org.scalacheck.Gen.Choose]] instances */ + object Choose { + + private def chLng(l: Long, h: Long)(p: P): R[Long] = { + if (h < l) r(None) else { + val d = h - l + 1 + if (d <= 0) { + var n = p.rng.nextLong + while (n < l || n > h) { + n = p.rng.nextLong + } + r(Some(n)) + } else { + r(Some(l + math.abs(p.rng.nextLong % d))) + } + } + } + + private def chDbl(l: Double, h: Double)(p: P): R[Double] = { + val d = h-l + if (d < 0 || d > Double.MaxValue) r(None) + else if (d == 0) r(Some(l)) + else r(Some(p.rng.nextDouble * (h-l) + l)) + } + + implicit val chooseLong: Choose[Long] = new Choose[Long] { + def choose(low: Long, high: Long) = + gen(chLng(low,high)).suchThat(x => x >= low && x <= high) + } + implicit val chooseInt: Choose[Int] = new Choose[Int] { + def choose(low: Int, high: Int) = + gen(chLng(low,high)).map(_.toInt).suchThat(x => x >= low && x <= high) + } + implicit val chooseByte: Choose[Byte] = new Choose[Byte] { + def choose(low: Byte, high: Byte) = + gen(chLng(low,high)).map(_.toByte).suchThat(x => x >= low && x <= high) + } + implicit val chooseShort: Choose[Short] = new Choose[Short] { + def choose(low: Short, high: Short) = + gen(chLng(low,high)).map(_.toShort).suchThat(x => x >= low && x <= high) + } + implicit val chooseChar: Choose[Char] = new Choose[Char] { + def choose(low: Char, high: Char) = + gen(chLng(low,high)).map(_.toChar).suchThat(x => x >= low && x <= high) + } + implicit val chooseDouble: Choose[Double] = new Choose[Double] { + def choose(low: Double, high: Double) = + gen(chDbl(low,high)).suchThat(x => x >= low && x <= high) + } + implicit val chooseFloat: Choose[Float] = new Choose[Float] { + def choose(low: Float, high: Float) = + gen(chDbl(low,high)).map(_.toFloat).suchThat(x => x >= low && x <= high) + } + + /** Transform a Choose[T] to a Choose[U] where T and U are two isomorphic types + * whose relationship is described by the provided transformation functions. + * (exponential functor map) */ + def xmap[T, U](from: T => U, to: U => T)(implicit c: Choose[T]): Choose[U] = new Choose[U] { + def choose(low: U, high: U) = + c.choose(to(low), to(high)).map(from) + } + } + + + //// Various Generator Combinators //// + + /** A generator that always generates the given value */ + @deprecated("Use Gen.const instead", "1.11.0") + def value[T](x: T): Gen[T] = const(x) + + /** A generator that always generates the given value */ + implicit def const[T](x: T): Gen[T] = gen(_ => r(Some(x))).suchThat(_ == x) + + /** A generator that never generates a value */ + def fail[T]: Gen[T] = gen(_ => r(None)).suchThat(_ => false) + + /** A generator that generates a random value in the given (inclusive) + * range. If the range is invalid, the generator will not generate + * any value. */ + def choose[T](min: T, max: T)(implicit c: Choose[T]): Gen[T] = + c.choose(min, max) + + /** Sequences generators. If any of the given generators fails, the + * resulting generator will also fail. */ + def sequence[C[_],T](gs: Traversable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C[T]] = { + val g = gen { p => + gs.foldLeft(r(Some(collection.immutable.Vector.empty[T]))) { + case (rs,g) => g.doApply(p).flatMap(r => rs.map(_ :+ r)) + } + } + g.map(b.fromIterable) + } + + /** Sequences generators. If any of the given generators fails, the + * resulting generator will also fail. */ + def sequence[C[_,_],T,U](gs: Traversable[Gen[(T,U)]])(implicit b: Buildable2[T,U,C]): Gen[C[T,U]] = { + val g = gen { p => + gs.foldLeft(r(Some(collection.immutable.Vector.empty[(T,U)]))) { + case (rs,g) => g.doApply(p).flatMap(r => rs.map(_ :+ r)) + } + } + g.map(b.fromIterable) + } + + /** Wraps a generator lazily. The given parameter is only evaluated once, + * and not until the wrapper generator is evaluated. */ + def lzy[T](g: => Gen[T]): Gen[T] = { + lazy val h = g + gen { p => h.doApply(p) } + } + + /** Wraps a generator for later evaluation. The given parameter is + * evaluated each time the wrapper generator is evaluated. */ + def wrap[T](g: => Gen[T]) = gen { p => g.doApply(p) } + + /** Creates a generator that can access its generation parameters */ + def parameterized[T](f: Parameters => Gen[T]) = gen { p => f(p).doApply(p) } + + /** Creates a generator that can access its generation size */ + def sized[T](f: Int => Gen[T]) = gen { p => f(p.size).doApply(p) } + + /** A generator that returns the current generation size */ + lazy val size: Gen[Int] = sized { sz => sz } + + /** Creates a resized version of a generator */ + def resize[T](s: Int, g: Gen[T]) = gen(p => g.doApply(p.withSize(s))) + + /** Picks a random value from a list */ + def oneOf[T](xs: Seq[T]): Gen[T] = + choose(0, xs.size-1).map(xs(_)).suchThat(xs.contains) + + /** Picks a random value from a list */ + def oneOf[T](t0: T, t1: T, tn: T*): Gen[T] = oneOf(t0 +: t1 +: tn) + + /** Picks a random generator from a list */ + def oneOf[T](g0: Gen[T], g1: Gen[T], gn: Gen[T]*): Gen[T] = { + val gs = g0 +: g1 +: gn + choose(0,gs.size-1).flatMap(gs(_)).suchThat(x => gs.exists(_.sieveCopy(x))) + } + + /** Makes a generator result optional. Either `Some(T)` or `None` will be provided. */ + def option[T](g: Gen[T]): Gen[Option[T]] = + oneOf[Option[T]](g.map(Some.apply), None) + + /** Chooses one of the given generators with a weighted random distribution */ + def frequency[T](gs: (Int,Gen[T])*): Gen[T] = { + gs.filter(_._1 > 0) match { + case Nil => fail + case filtered => + var tot = 0l + val tree: TreeMap[Long, Gen[T]] = { + val builder = TreeMap.newBuilder[Long, Gen[T]] + filtered.foreach { + case (f, v) => + tot += f + builder.+=((tot, v)) + } + builder.result() + } + choose(1L, tot).flatMap(r => tree.from(r).head._2).suchThat { x => + gs.exists(_._2.sieveCopy(x)) + } + } + } + + /** Implicit convenience method for using the `frequency` method + * like this: + * {{{ + * frequency((1, "foo"), (3, "bar")) + * }}} + */ + implicit def freqTuple[T](t: (Int,T)): (Int,Gen[T]) = (t._1, const(t._2)) + + + //// List Generators //// + + /** Generates a container of any Traversable type for which there exists an + * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the + * container will be generated by the given generator. The size of the + * generated container is limited by `n`. Depending on what kind of container + * that is generated, the resulting container may contain fewer elements than + * `n`, but not more. If the given generator fails generating a value, the + * complete container generator will also fail. */ + def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit + evb: Buildable[T,C], evt: C[T] => Traversable[T] + ): Gen[C[T]] = + sequence[C,T](Traversable.fill(n)(g)) suchThat { c => + // TODO: Can we guarantee c.size == n (See issue #89)? + c.forall(g.sieveCopy) + } + + /** Generates a container of any Traversable type for which there exists an + * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the + * container will be generated by the given generator. The size of the + * container is bounded by the size parameter used when generating values. */ + def containerOf[C[_],T](g: Gen[T])(implicit + evb: Buildable[T,C], evt: C[T] => Traversable[T] + ): Gen[C[T]] = + sized(s => choose(0,s).flatMap(containerOfN[C,T](_,g))) suchThat { c => + c.forall(g.sieveCopy) + } + + /** Generates a non-empty container of any Traversable type for which there + * exists an implicit [[org.scalacheck.util.Buildable]] instance. The + * elements in the container will be generated by the given generator. The + * size of the container is bounded by the size parameter used when + * generating values. */ + def nonEmptyContainerOf[C[_],T](g: Gen[T])(implicit + evb: Buildable[T,C], evt: C[T] => Traversable[T] + ): Gen[C[T]] = + sized(s => choose(1,s).flatMap(containerOfN[C,T](_,g))) suchThat { c => + c.size > 0 && c.forall(g.sieveCopy) + } + + /** Generates a non-empty container of any Traversable type for which there + * exists an implicit [[org.scalacheck.util.Buildable]] instance. The + * elements in the container will be generated by the given generator. The + * size of the container is bounded by the size parameter used when + * generating values. */ + @deprecated("Use Gen.nonEmptyContainerOf instead", "1.11.0") + def containerOf1[C[_],T](g: Gen[T])(implicit + evb: Buildable[T,C], evt: C[T] => Traversable[T] + ): Gen[C[T]] = nonEmptyContainerOf[C,T](g) + + /** Generates a container of any Traversable type for which there exists an + * implicit [[org.scalacheck.util.Buildable2]] instance. The elements in + * container will be generated by the given generator. The size of the + * generated container is limited by `n`. Depending on what kind of container + * that is generated, the resulting container may contain fewer elements than + * `n`, but not more. If the given generator fails generating a value, the + * complete container generator will also fail. */ + def containerOfN[C[_,_],T,U](n: Int, g: Gen[(T,U)])(implicit + evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)] + ): Gen[C[T,U]] = + sequence[C,T,U](Traversable.fill(n)(g)).suchThat { c => + // TODO: Can we guarantee c.size == n (See issue #89)? + c.forall(g.sieveCopy) + } + + /** Generates a container of any Traversable type for which there exists + * an implicit Buildable2 instance. The elements in the + * container will be generated by the given generator. The size of the + * container is bounded by the size parameter used when generating values. */ + def containerOf[C[_,_],T,U](g: Gen[(T,U)])(implicit + evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)] + ): Gen[C[T,U]] = + sized(s => choose(0,s).flatMap(containerOfN[C,T,U](_,g))) suchThat { c => + c.forall(g.sieveCopy) + } + + /** Generates a non-empty container of any type for which there exists an + * implicit Buildable2 instance. The elements in the container + * will be generated by the given generator. The size of the container is + * bounded by the size parameter used when generating values. */ + def nonEmptyContainerOf[C[_,_],T,U](g: Gen[(T,U)])(implicit + evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)] + ): Gen[C[T,U]] = + sized(s => choose(1,s).flatMap(containerOfN[C,T,U](_,g))) suchThat { c => + c.size > 0 && c.forall(g.sieveCopy) + } + + /** Generates a list of random length. The maximum length depends on the + * size parameter. This method is equal to calling + * `containerOf[List,T](g)`. */ + def listOf[T](g: => Gen[T]) = containerOf[List,T](g) + + /** Generates a non-empty list of random length. The maximum length depends + * on the size parameter. This method is equal to calling + * `nonEmptyContainerOf[List,T](g)`. */ + def nonEmptyListOf[T](g: => Gen[T]) = nonEmptyContainerOf[List,T](g) + + /** Generates a non-empty list of random length. The maximum length depends + * on the size parameter. This method is equal to calling + * `nonEmptyContainerOf[List,T](g)`. */ + @deprecated("Use Gen.nonEmptyListOf instead", "1.11.0") + def listOf1[T](g: => Gen[T]) = nonEmptyListOf[T](g) + + /** Generates a list of the given length. This method is equal to calling + * `containerOfN[List,T](n,g)`. */ + def listOfN[T](n: Int, g: Gen[T]) = containerOfN[List,T](n,g) + + /** Generates a map of random length. The maximum length depends on the + * size parameter. This method is equal to calling + * containerOf[Map,T,U](g). */ + def mapOf[T,U](g: => Gen[(T,U)]) = containerOf[Map,T,U](g) + + /** Generates a non-empty map of random length. The maximum length depends + * on the size parameter. This method is equal to calling + * nonEmptyContainerOf[Map,T,U](g). */ + def nonEmptyMap[T,U](g: => Gen[(T,U)]) = nonEmptyContainerOf[Map,T,U](g) + + /** Generates a map of with at least the given number of elements. This method + * is equal to calling containerOfN[Map,T,U](n,g). */ + def mapOfN[T,U](n: Int, g: Gen[(T,U)]) = containerOfN[Map,T,U](n,g) + + /** A generator that picks a random number of elements from a list */ + def someOf[T](l: Iterable[T]) = choose(0,l.size).flatMap(pick(_,l)) + + /** A generator that picks a random number of elements from a list */ + def someOf[T](g1: Gen[T], g2: Gen[T], gs: Gen[T]*) = + choose(0, gs.length+2).flatMap(pick(_, g1, g2, gs: _*)) + + /** A generator that picks a given number of elements from a list, randomly */ + def pick[T](n: Int, l: Iterable[T]): Gen[Seq[T]] = + if(n > l.size || n < 0) fail + else (gen { p => + val b = new collection.mutable.ListBuffer[T] + b ++= l + while(b.length > n) b.remove(choose(0, b.length-1).doApply(p).retrieve.get) + r(Some(b)) + }).suchThat(_.forall(x => l.exists(x == _))) + + /** A generator that picks a given number of elements from a list, randomly */ + def pick[T](n: Int, g1: Gen[T], g2: Gen[T], gn: Gen[T]*): Gen[Seq[T]] = { + val gs = g1 +: g2 +: gn + pick(n, 0 until gs.size).flatMap(idxs => + sequence[List,T](idxs.toList.map(gs(_))) + ).suchThat(_.forall(x => gs.exists(_.sieveCopy(x)))) + } + + + //// Character Generators //// + + /** Generates a numerical character */ + def numChar: Gen[Char] = choose(48.toChar, 57.toChar) + + /** Generates an upper-case alpha character */ + def alphaUpperChar: Gen[Char] = choose(65.toChar, 90.toChar) + + /** Generates a lower-case alpha character */ + def alphaLowerChar: Gen[Char] = choose(97.toChar, 122.toChar) + + /** Generates an alpha character */ + def alphaChar = frequency((1,alphaUpperChar), (9,alphaLowerChar)) + + /** Generates an alphanumerical character */ + def alphaNumChar = frequency((1,numChar), (9,alphaChar)) + + + //// String Generators //// + + /** Generates a string that starts with a lower-case alpha character, + * and only contains alphanumerical characters */ + def identifier: Gen[String] = (for { + c <- alphaLowerChar + cs <- listOf(alphaNumChar) + } yield (c::cs).mkString).suchThat(_.forall(c => c.isLetter || c.isDigit)) + + /** Generates a string of alpha characters */ + def alphaStr: Gen[String] = + listOf(alphaChar).map(_.mkString).suchThat(_.forall(_.isLetter)) + + /** Generates a string of digits */ + def numStr: Gen[String] = + listOf(numChar).map(_.mkString).suchThat(_.forall(_.isDigit)) + + + //// Number Generators //// + + /** Generates positive numbers of uniform distribution, with an + * upper bound of the generation size parameter. */ + def posNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = { + import num._ + sized(max => c.choose(one, fromInt(max))) + } + + /** Generates negative numbers of uniform distribution, with an + * lower bound of the negated generation size parameter. */ + def negNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = { + import num._ + sized(max => c.choose(-fromInt(max), -one)) + } + + /** Generates numbers within the given inclusive range, with + * extra weight on zero, +/- unity, both extremities, and any special + * numbers provided. The special numbers must lie within the given range, + * otherwise they won't be included. */ + def chooseNum[T](minT: T, maxT: T, specials: T*)( + implicit num: Numeric[T], c: Choose[T] + ): Gen[T] = { + import num._ + val basics = List(minT, maxT, zero, one, -one) + val basicsAndSpecials = for { + t <- specials ++ basics if t >= minT && t <= maxT + } yield (1, const(t)) + val allGens = basicsAndSpecials ++ List( + (basicsAndSpecials.length, c.choose(minT, maxT)) + ) + frequency(allGens: _*) + } + + /** Generates a version 4 (random) UUID. */ + lazy val uuid: Gen[java.util.UUID] = for { + l1 <- Gen.choose(Long.MinValue, Long.MaxValue) + l2 <- Gen.choose(Long.MinValue, Long.MaxValue) + y <- Gen.oneOf('8', '9', 'a', 'b') + } yield java.util.UUID.fromString( + new java.util.UUID(l1,l2).toString.updated(14, '4').updated(19, y) + ) + + /** Combines the given generators into one generator that produces a + * tuple of their generated values. */ + def zip[T1,T2](g1: Gen[T1], g2: Gen[T2]): Gen[(T1,T2)] = { + val g = for { + t1 <- g1; t2 <- g2 + } yield (t1,t2) + g.suchThat { case (t1,t2) => g1.sieveCopy(t1) && g2.sieveCopy(t2) } + } + + /** Combines the given generators into one generator that produces a + * tuple of their generated values. */ + def zip[T1,T2,T3](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3]): Gen[(T1,T2,T3)] = { + val g0 = zip(g1,g2) + val g = for { + (t1,t2) <- g0; t3 <- g3 + } yield (t1,t2,t3) + g.suchThat { case (t1,t2,t3) => g0.sieveCopy(t1,t2) && g3.sieveCopy(t3) } + } + + /** Combines the given generators into one generator that produces a + * tuple of their generated values. */ + def zip[T1,T2,T3,T4](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4] + ): Gen[(T1,T2,T3,T4)] = { + val g0 = zip(g1,g2,g3) + val g = for { + (t1,t2,t3) <- g0; t4 <- g4 + } yield (t1,t2,t3,t4) + g.suchThat { case (t1,t2,t3,t4) => g0.sieveCopy(t1,t2,t3) && g4.sieveCopy(t4) } + } + + /** Combines the given generators into one generator that produces a + * tuple of their generated values. */ + def zip[T1,T2,T3,T4,T5](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], + g5: Gen[T5] + ): Gen[(T1,T2,T3,T4,T5)] = { + val g0 = zip(g1,g2,g3,g4) + val g = for { + (t1,t2,t3,t4) <- g0; t5 <- g5 + } yield (t1,t2,t3,t4,t5) + g.suchThat { case (t1,t2,t3,t4,t5) => + g0.sieveCopy(t1,t2,t3,t4) && g5.sieveCopy(t5) + } + } + + /** Combines the given generators into one generator that produces a + * tuple of their generated values. */ + def zip[T1,T2,T3,T4,T5,T6](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], + g5: Gen[T5], g6: Gen[T6] + ): Gen[(T1,T2,T3,T4,T5,T6)] = { + val g0 = zip(g1,g2,g3,g4,g5) + val g = for { + (t1,t2,t3,t4,t5) <- g0; t6 <- g6 + } yield (t1,t2,t3,t4,t5,t6) + g.suchThat { case (t1,t2,t3,t4,t5,t6) => + g0.sieveCopy(t1,t2,t3,t4,t5) && g6.sieveCopy(t6) + } + } + + /** Combines the given generators into one generator that produces a + * tuple of their generated values. */ + def zip[T1,T2,T3,T4,T5,T6,T7](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], + g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7] + ): Gen[(T1,T2,T3,T4,T5,T6,T7)] = { + val g0 = zip(g1,g2,g3,g4,g5,g6) + val g = for { + (t1,t2,t3,t4,t5,t6) <- g0; t7 <- g7 + } yield (t1,t2,t3,t4,t5,t6,t7) + g.suchThat { case (t1,t2,t3,t4,t5,t6,t7) => + g0.sieveCopy(t1,t2,t3,t4,t5,t6) && g7.sieveCopy(t7) + } + } + + /** Combines the given generators into one generator that produces a + * tuple of their generated values. */ + def zip[T1,T2,T3,T4,T5,T6,T7,T8](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], + g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7], g8: Gen[T8] + ): Gen[(T1,T2,T3,T4,T5,T6,T7,T8)] = { + val g0 = zip(g1,g2,g3,g4,g5,g6,g7) + val g = for { + (t1,t2,t3,t4,t5,t6,t7) <- g0; t8 <- g8 + } yield (t1,t2,t3,t4,t5,t6,t7,t8) + g.suchThat { case (t1,t2,t3,t4,t5,t6,t7,t8) => + g0.sieveCopy(t1,t2,t3,t4,t5,t6,t7) && g8.sieveCopy(t8) + } + } + + /** Combines the given generators into one generator that produces a + * tuple of their generated values. */ + def zip[T1,T2,T3,T4,T5,T6,T7,T8,T9](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], + g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7], g8: Gen[T8], g9: Gen[T9] + ): Gen[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] = { + val g0 = zip(g1,g2,g3,g4,g5,g6,g7,g8) + val g = for { + (t1,t2,t3,t4,t5,t6,t7,t8) <- g0; t9 <- g9 + } yield (t1,t2,t3,t4,t5,t6,t7,t8,t9) + g.suchThat { case (t1,t2,t3,t4,t5,t6,t7,t8,t9) => + g0.sieveCopy(t1,t2,t3,t4,t5,t6,t7,t8) && g9.sieveCopy(t9) + } + } + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T,R](f: T => R)(implicit a: Arbitrary[T]): Gen[R] = + arbitrary[T] map f + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T1,T2,R](f: (T1,T2) => R)(implicit + a1: Arbitrary[T1], a2: Arbitrary[T2] + ): Gen[R] = arbitrary[T1] flatMap { t => resultOf(f(t, _:T2)) } + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T1,T2,T3,R](f: (T1,T2,T3) => R)(implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3] + ): Gen[R] = arbitrary[T1] flatMap { t => resultOf(f(t, _:T2, _:T3)) } + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T1,T2,T3,T4,R](f: (T1,T2,T3,T4) => R)(implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4] + ): Gen[R] = arbitrary[T1] flatMap { + t => resultOf(f(t, _:T2, _:T3, _:T4)) + } + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T1,T2,T3,T4,T5,R](f: (T1,T2,T3,T4,T5) => R)(implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4], + a5: Arbitrary[T5] + ): Gen[R] = arbitrary[T1] flatMap { + t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5)) + } + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T1,T2,T3,T4,T5,T6,R]( + f: (T1,T2,T3,T4,T5,T6) => R)(implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], + a4: Arbitrary[T4], a5: Arbitrary[T5], a6: Arbitrary[T6] + ): Gen[R] = arbitrary[T1] flatMap { + t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5, _:T6)) + } + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T1,T2,T3,T4,T5,T6,T7,R]( + f: (T1,T2,T3,T4,T5,T6,T7) => R)(implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], + a4: Arbitrary[T4], a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7] + ): Gen[R] = arbitrary[T1] flatMap { + t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7)) + } + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T1,T2,T3,T4,T5,T6,T7,T8,R]( + f: (T1,T2,T3,T4,T5,T6,T7,T8) => R)(implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4], + a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7], a8: Arbitrary[T8] + ): Gen[R] = arbitrary[T1] flatMap { + t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7, _:T8)) + } + + /** Takes a function and returns a generator that generates arbitrary + * results of that function by feeding it with arbitrarily generated input + * parameters. */ + def resultOf[T1,T2,T3,T4,T5,T6,T7,T8,T9,R]( + f: (T1,T2,T3,T4,T5,T6,T7,T8,T9) => R)(implicit + a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4], + a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7], a8: Arbitrary[T8], + a9: Arbitrary[T9] + ): Gen[R] = arbitrary[T1] flatMap { + t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7, _:T8, _:T9)) + } +} diff --git a/src/partest-extras/scala/org/scalacheck/Prop.scala b/src/partest-extras/scala/org/scalacheck/Prop.scala new file mode 100644 index 000000000000..6b607002fd22 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/Prop.scala @@ -0,0 +1,953 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +import util.{Pretty, FreqMap, Buildable, ConsoleReporter} +import scala.annotation.tailrec + +trait Prop { + + import Prop.{Result, Proof, True, False, Exception, Undecided, + provedToTrue, secure, mergeRes} + import Gen.Parameters + + def apply(prms: Parameters): Result + + def map(f: Result => Result): Prop = Prop(prms => f(this(prms))) + + def flatMap(f: Result => Prop): Prop = Prop(prms => f(this(prms))(prms)) + + // TODO In 1.12.0, make p call-by-name, and remove the calls to secure() + // in the methods that use combine() + def combine(p: Prop)(f: (Result, Result) => Result) = + for(r1 <- this; r2 <- p) yield f(r1,r2) + + /** Convenience method that checks this property with the given parameters + * and reports the result on the console. */ + def check(prms: Test.Parameters): Unit = Test.check( + if(prms.testCallback.isInstanceOf[ConsoleReporter]) prms + else prms.withTestCallback(prms.testCallback.chain(ConsoleReporter(1))), + this + ) + + /** Convenience method that checks this property and reports the + * result on the console. The default test parameters + * ([[Test.Parameters.default]]) are used for the check. */ + def check: Unit = check(Test.Parameters.default) + + /** Convenience method that checks this property and reports the result + * on the console. The provided argument should be a function that takes + * the default test parameters ([[Test.Parameters.default]]) + * as input and outputs a modified [[Test.Parameters]] instance that + * Example use: + * + * {{{ + * p.check(_.withMinSuccessfulTests(500)) + + * p.check { _. + * withMinSuccessfulTests(80000). + * withWorkers(4) + * } + * }}} + */ + def check(paramFun: Test.Parameters => Test.Parameters): Unit = check( + paramFun(Test.Parameters.default) + ) + + /** Convenience method that checks this property with specified minimal + * number of successful test and the given testing parameters, and + * reports the result on the console. If you need to get the results + * from the test use the `check` methods in [[org.scalacheck.Test]] + * instead. */ + @deprecated("Use check(prms.withMinSuccessfulTests(n)) instead", "1.11.2") + def check(minSuccessfulTests: Int, prms: Test.Parameters): Unit = check( + prms.withMinSuccessfulTests(minSuccessfulTests) + ) + + /** Convenience method that checks this property with specified minimal + * number of successful test and reports the result on the console. + * If you need to get the results from the test use + * the `check` methods in [[org.scalacheck.Test]] instead. */ + @deprecated("Use check(_.withMinSuccessfulTests(n)) instead", "1.11.2") + def check(minSuccessfulTests: Int): Unit = check( + _.withMinSuccessfulTests(minSuccessfulTests) + ) + + /** The logic for main, separated out to make it easier to + * avoid System.exit calls. Returns exit code. + */ + def mainRunner(args: Array[String]): Int = { + Test.parseParams(args) match { + case Some(params) => + if (Test.check(params, this).passed) 0 + else 1 + case None => + println("Incorrect options") + -1 + } + } + + /** Whether main should call System.exit with an exit code. + * Defaults to true; override to change. */ + def mainCallsExit = true + + /** Convenience method that makes it possible to use this property + * as an application that checks itself on execution */ + def main(args: Array[String]): Unit = { + val code = mainRunner(args) + if (mainCallsExit && code != 0) + System exit code + } + + /** Returns a new property that holds if and only if both this + * and the given property hold. If one of the properties doesn't + * generate a result, the new property will generate false. */ + def &&(p: => Prop) = combine(secure(p))(_ && _) + + /** Returns a new property that holds if either this + * or the given property (or both) hold. */ + def ||(p: => Prop) = combine(secure(p))(_ || _) + + /** Returns a new property that holds if and only if both this + * and the given property hold. If one of the properties doesn't + * generate a result, the new property will generate the same result + * as the other property. */ + def ++(p: => Prop): Prop = combine(secure(p))(_ ++ _) + + /** Combines two properties through implication */ + def ==>(p: => Prop): Prop = flatMap { r1 => + if(r1.proved) p map { r2 => mergeRes(r1,r2,r2.status) } + else if(!r1.success) Prop(r1.copy(status = Undecided)) + else p map { r2 => provedToTrue(mergeRes(r1,r2,r2.status)) } + } + + /** Returns a new property that holds if and only if both this + * and the given property generates a result with the exact + * same status. Note that this means that if one of the properties is + * proved, and the other one passed, then the resulting property + * will fail. */ + def ==(p: => Prop) = this.flatMap { r1 => + p.map { r2 => + mergeRes(r1, r2, if(r1.status == r2.status) True else False) + } + } + + override def toString = "Prop" + + /** Put a label on the property to make test reports clearer */ + def label(l: String) = map(_.label(l)) + + /** Put a label on the property to make test reports clearer */ + def :|(l: String) = label(l) + + /** Put a label on the property to make test reports clearer */ + def |:(l: String) = label(l) + + /** Put a label on the property to make test reports clearer */ + def :|(l: Symbol) = label(l.toString.drop(1)) + + /** Put a label on the property to make test reports clearer */ + def |:(l: Symbol) = label(l.toString.drop(1)) + +} + +object Prop { + + import Gen.{value, fail, frequency, oneOf, Parameters} + import Arbitrary.{arbitrary} + import Shrink.{shrink} + + // Types + + /** A property argument */ + case class Arg[+T]( + label: String, + arg: T, + shrinks: Int, + origArg: T, + prettyArg: Pretty, + prettyOrigArg: Pretty + ) + + object Result { + @deprecated("Will be removed in 1.12.0", "1.11.2") + def apply(st: Status): Result = Result(status = st) + @deprecated("Will be removed in 1.12.0", "1.11.2") + def merge(x: Result, y: Result, status: Status) = mergeRes(x,y,status) + } + + private[scalacheck] def mergeRes(x: Result, y: Result, st: Status) = Result( + status = st, + args = x.args ++ y.args, + collected = x.collected ++ y.collected, + labels = x.labels ++ y.labels + ) + + /** The result of evaluating a property */ + case class Result( + status: Status, + args: List[Arg[Any]] = Nil, + collected: Set[Any] = Set.empty, + labels: Set[String] = Set.empty + ) { + def success = status match { + case True => true + case Proof => true + case _ => false + } + + def failure = status match { + case False => true + case Exception(_) => true + case _ => false + } + + def proved = status == Proof + + def addArg(a: Arg[Any]) = copy(args = a::args) + + def collect(x: Any) = copy(collected = collected+x) + + def label(l: String) = copy(labels = labels+l) + + def &&(r: Result) = (this.status, r.status) match { + case (Exception(_),_) => this + case (_,Exception(_)) => r + + case (False,_) => this + case (_,False) => r + + case (Undecided,_) => this + case (_,Undecided) => r + + case (_,Proof) => mergeRes(this, r, this.status) + case (Proof,_) => mergeRes(this, r, r.status) + + case (True,True) => mergeRes(this, r, True) + } + + def ||(r: Result) = (this.status, r.status) match { + case (Exception(_),_) => this + case (_,Exception(_)) => r + + case (False,False) => mergeRes(this, r, False) + case (False,_) => r + case (_,False) => this + + case (Proof,_) => this + case (_,Proof) => r + + case (True,_) => this + case (_,True) => r + + case (Undecided,Undecided) => mergeRes(this, r, Undecided) + } + + def ++(r: Result) = (this.status, r.status) match { + case (Exception(_),_) => this + case (_,Exception(_)) => r + + case (_, Undecided) => this + case (Undecided, _) => r + + case (_, Proof) => this + case (Proof, _) => r + + case (_, True) => this + case (True, _) => r + + case (False, _) => this + case (_, False) => r + } + + def ==>(r: Result) = (this.status, r.status) match { + case (Exception(_),_) => this + case (_,Exception(_)) => r + + case (False,_) => mergeRes(this, r, Undecided) + + case (Undecided,_) => this + + case (Proof,_) => mergeRes(this, r, r.status) + case (True,_) => mergeRes(this, r, r.status) + } + } + + sealed trait Status + + /** The property was proved */ + case object Proof extends Status + + /** The property was true */ + case object True extends Status + + /** The property was false */ + case object False extends Status + + /** The property could not be falsified or proved */ + case object Undecided extends Status + + /** Evaluating the property raised an exception */ + sealed case class Exception(e: Throwable) extends Status { + override def equals(o: Any) = o match { + case Exception(_) => true + case _ => false + } + } + + /** Create a new property from the given function. */ + def apply(f: Parameters => Result): Prop = new Prop { + def apply(prms: Parameters) = try f(prms) catch { + case e: Throwable => Result(status = Exception(e)) + } + } + + /** Create a property that returns the given result */ + def apply(r: Result): Prop = Prop.apply(prms => r) + + /** Create a property from a boolean value */ + def apply(b: Boolean): Prop = if(b) proved else falsified + + + // Implicits + + /** A collection of property operators on `Any` values. + * Import [[Prop.AnyOperators]] to make the operators available. */ + class ExtendedAny[T <% Pretty](x: => T) { + /** See [[Prop.imply]] */ + def imply(f: PartialFunction[T,Prop]) = Prop.imply(x,f) + /** See [[Prop.iff]] */ + def iff(f: PartialFunction[T,Prop]) = Prop.iff(x,f) + /** See [[Prop.?=]] */ + def ?=(y: T) = Prop.?=(x, y) + /** See [[Prop.=?]] */ + def =?(y: T) = Prop.=?(x, y) + } + + /** A collection of property operators on `Boolean` values. + * Import [[Prop.BooleanOperators]] to make the operators available. */ + class ExtendedBoolean(b: => Boolean) { + /** See the documentation for [[org.scalacheck.Prop]] */ + def ==>(p: => Prop) = Prop(b) ==> p + /** See the documentation for [[org.scalacheck.Prop]] */ + def :|(l: String) = Prop(b) :| l + /** See the documentation for [[org.scalacheck.Prop]] */ + def |:(l: String) = l |: Prop(b) + /** See the documentation for [[org.scalacheck.Prop]] */ + def :|(l: Symbol) = Prop(b) :| l + /** See the documentation for [[org.scalacheck.Prop]] */ + def |:(l: Symbol) = l |: Prop(b) + } + + /** Implicit method that makes a number of property operators on values of + * type `Any` available in the current scope. + * See [[Prop.ExtendedAny]] for documentation on the operators. */ + implicit def AnyOperators[T <% Pretty](x: => T) = new ExtendedAny[T](x) + + /** Implicit method that makes a number of property operators on boolean + * values available in the current scope. See [[Prop.ExtendedBoolean]] for + * documentation on the operators. */ + implicit def BooleanOperators(b: => Boolean) = new ExtendedBoolean(b) + + /** Implicit conversion of Boolean values to Prop values. */ + implicit def propBoolean(b: Boolean): Prop = Prop(b) + + + // Private support functions + + private def provedToTrue(r: Result) = r.status match { + case Proof => r.copy(status = True) + case _ => r + } + + + // Property combinators + + /** A property that never is proved or falsified */ + lazy val undecided = Prop(Result(status = Undecided)) + + /** A property that always is false */ + lazy val falsified = Prop(Result(status = False)) + + /** A property that always is proved */ + lazy val proved = Prop(Result(status = Proof)) + + /** A property that always is passed */ + lazy val passed = Prop(Result(status = True)) + + /** A property that denotes an exception */ + def exception(e: Throwable): Prop = Prop(Result(status = Exception(e))) + + /** A property that denotes an exception */ + lazy val exception: Prop = exception(null) + + /** Create a property that compares to values. If the values aren't equal, + * the property will fail and report that first value doesn't match the + * expected (second) value. */ + def ?=[T](x: T, y: T)(implicit pp: T => Pretty): Prop = + if(x == y) proved else falsified :| { + val exp = Pretty.pretty[T](y, Pretty.Params(0)) + val act = Pretty.pretty[T](x, Pretty.Params(0)) + "Expected "+exp+" but got "+act + } + + /** Create a property that compares to values. If the values aren't equal, + * the property will fail and report that second value doesn't match the + * expected (first) value. */ + def =?[T](x: T, y: T)(implicit pp: T => Pretty): Prop = ?=(y, x) + + /** A property that depends on the generator size */ + def sizedProp(f: Int => Prop): Prop = Prop { prms => + // provedToTrue since if the property is proved for + // one size, it shouldn't be regarded as proved for + // all sizes. + provedToTrue(f(prms.size)(prms)) + } + + /** Implication with several conditions */ + def imply[T](x: T, f: PartialFunction[T,Prop]): Prop = secure { + if(f.isDefinedAt(x)) f(x) else undecided + } + + /** Property holds only if the given partial function is defined at + * `x`, and returns a property that holds */ + def iff[T](x: T, f: PartialFunction[T,Prop]): Prop = secure { + if(f.isDefinedAt(x)) f(x) else falsified + } + + /** Combines properties into one, which is true if and only if all the + * properties are true */ + def all(ps: Prop*) = if(ps.isEmpty) proved else Prop(prms => + ps.map(p => p(prms)).reduceLeft(_ && _) + ) + + /** Combines properties into one, which is true if at least one of the + * properties is true */ + def atLeastOne(ps: Prop*) = if(ps.isEmpty) falsified else Prop(prms => + ps.map(p => p(prms)).reduceLeft(_ || _) + ) + + /** A property that holds if at least one of the given generators + * fails generating a value */ + def someFailing[T](gs: Seq[Gen[T]]) = atLeastOne(gs.map(_ == fail):_*) + + /** A property that holds iff none of the given generators + * fails generating a value */ + def noneFailing[T](gs: Seq[Gen[T]]) = all(gs.map(_ !== fail):_*) + + /** Returns true if the given statement throws an exception + * of the specified type */ + def throws[T <: Throwable](c: Class[T])(x: => Any): Boolean = + try { x; false } catch { case e if c.isInstance(e) => true } + + /** Collect data for presentation in test report */ + def collect[T, P <% Prop](f: T => P): T => Prop = t => Prop { prms => + val prop = f(t) + prop(prms).collect(t) + } + + /** Collect data for presentation in test report */ + def collect[T](t: T)(prop: Prop) = Prop { prms => + prop(prms).collect(t) + } + + /** Collect data for presentation in test report */ + def classify(c: => Boolean, ifTrue: Any)(prop: Prop): Prop = + if(c) collect(ifTrue)(prop) else collect(())(prop) + + /** Collect data for presentation in test report */ + def classify(c: => Boolean, ifTrue: Any, ifFalse: Any)(prop: Prop): Prop = + if(c) collect(ifTrue)(prop) else collect(ifFalse)(prop) + + /** Wraps and protects a property */ + def secure[P <% Prop](p: => P): Prop = + try (p: Prop) catch { case e: Throwable => exception(e) } + + /** Existential quantifier for an explicit generator. */ + def exists[A,P](f: A => P)(implicit + pv: P => Prop, + pp: A => Pretty, + aa: Arbitrary[A] + ): Prop = exists(aa.arbitrary)(f) + + /** Existential quantifier for an explicit generator. */ + def exists[A,P](g: Gen[A])(f: A => P)(implicit + pv: P => Prop, + pp: A => Pretty + ): Prop = Prop { prms => + val gr = g.doApply(prms) + gr.retrieve match { + case None => undecided(prms) + case Some(x) => + val p = secure(f(x)) + val labels = gr.labels.mkString(",") + val r = p(prms).addArg(Arg(labels,x,0,x,pp(x),pp(x))) + r.status match { + case True => r.copy(status = Proof) + case False => r.copy(status = Undecided) + case _ => r + } + } + } + + /** Universal quantifier for an explicit generator. Does not shrink failed + * test cases. */ + def forAllNoShrink[T1,P]( + g1: Gen[T1])( + f: T1 => P)(implicit + pv: P => Prop, + pp1: T1 => Pretty + ): Prop = Prop { prms => + val gr = g1.doApply(prms) + gr.retrieve match { + case None => undecided(prms) + case Some(x) => + val p = secure(f(x)) + val labels = gr.labels.mkString(",") + provedToTrue(p(prms)).addArg(Arg(labels,x,0,x,pp1(x),pp1(x))) + } + } + + /** Universal quantifier for two explicit generators. + * Does not shrink failed test cases. */ + def forAllNoShrink[T1,T2,P]( + g1: Gen[T1], g2: Gen[T2])( + f: (T1,T2) => P)(implicit + p: P => Prop, + pp1: T1 => Pretty, + pp2: T2 => Pretty + ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2)(f(t, _:T2))) + + /** Universal quantifier for three explicit generators. + * Does not shrink failed test cases. */ + def forAllNoShrink[T1,T2,T3,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3])( + f: (T1,T2,T3) => P)(implicit + p: P => Prop, + pp1: T1 => Pretty, + pp2: T2 => Pretty, + pp3: T3 => Pretty + ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3)(f(t, _:T2, _:T3))) + + /** Universal quantifier for four explicit generators. + * Does not shrink failed test cases. */ + def forAllNoShrink[T1,T2,T3,T4,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4])( + f: (T1,T2,T3,T4) => P)(implicit + p: P => Prop, + pp1: T1 => Pretty, + pp2: T2 => Pretty, + pp3: T3 => Pretty, + pp4: T4 => Pretty + ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4)(f(t, _:T2, _:T3, _:T4))) + + /** Universal quantifier for five explicit generators. + * Does not shrink failed test cases. */ + def forAllNoShrink[T1,T2,T3,T4,T5,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5])( + f: (T1,T2,T3,T4,T5) => P)(implicit + p: P => Prop, + pp1: T1 => Pretty, + pp2: T2 => Pretty, + pp3: T3 => Pretty, + pp4: T4 => Pretty, + pp5: T5 => Pretty + ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4,g5)(f(t, _:T2, _:T3, _:T4, _:T5))) + + /** Universal quantifier for six explicit generators. + * Does not shrink failed test cases. */ + def forAllNoShrink[T1,T2,T3,T4,T5,T6,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6])( + f: (T1,T2,T3,T4,T5,T6) => P)(implicit + p: P => Prop, + pp1: T1 => Pretty, + pp2: T2 => Pretty, + pp3: T3 => Pretty, + pp4: T4 => Pretty, + pp5: T5 => Pretty, + pp6: T6 => Pretty + ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4,g5,g6)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6))) + + /** Universal quantifier for seven explicit generators. + * Does not shrink failed test cases. */ + def forAllNoShrink[T1,T2,T3,T4,T5,T6,T7,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7])( + f: (T1,T2,T3,T4,T5,T6,T7) => P)(implicit + p: P => Prop, + pp1: T1 => Pretty, + pp2: T2 => Pretty, + pp3: T3 => Pretty, + pp4: T4 => Pretty, + pp5: T5 => Pretty, + pp6: T6 => Pretty, + pp7: T7 => Pretty + ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4,g5,g6,g7)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7))) + + /** Universal quantifier for eight explicit generators. + * Does not shrink failed test cases. */ + def forAllNoShrink[T1,T2,T3,T4,T5,T6,T7,T8,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7], g8: Gen[T8])( + f: (T1,T2,T3,T4,T5,T6,T7,T8) => P)(implicit + p: P => Prop, + pp1: T1 => Pretty, + pp2: T2 => Pretty, + pp3: T3 => Pretty, + pp4: T4 => Pretty, + pp5: T5 => Pretty, + pp6: T6 => Pretty, + pp7: T7 => Pretty, + pp8: T8 => Pretty + ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4,g5,g6,g7,g8)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7, _:T8))) + + /** Converts a function into a universally quantified property */ + def forAllNoShrink[A1,P]( + f: A1 => P)(implicit + pv: P => Prop, + a1: Arbitrary[A1], pp1: A1 => Pretty + ): Prop = forAllNoShrink(arbitrary[A1])(f) + + /** Converts a function into a universally quantified property */ + def forAllNoShrink[A1,A2,P]( + f: (A1,A2) => P)(implicit + pv: P => Prop, + a1: Arbitrary[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], pp2: A2 => Pretty + ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2])(f) + + /** Converts a function into a universally quantified property */ + def forAllNoShrink[A1,A2,A3,P]( + f: (A1,A2,A3) => P)(implicit + pv: P => Prop, + a1: Arbitrary[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], pp3: A3 => Pretty + ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3])(f) + + /** Converts a function into a universally quantified property */ + def forAllNoShrink[A1,A2,A3,A4,P]( + f: (A1,A2,A3,A4) => P)(implicit + pv: P => Prop, + a1: Arbitrary[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], pp4: A4 => Pretty + ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4])(f) + + /** Converts a function into a universally quantified property */ + def forAllNoShrink[A1,A2,A3,A4,A5,P]( + f: (A1,A2,A3,A4,A5) => P)(implicit + pv: P => Prop, + a1: Arbitrary[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], pp4: A4 => Pretty, + a5: Arbitrary[A5], pp5: A5 => Pretty + ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4], arbitrary[A5])(f) + + /** Converts a function into a universally quantified property */ + def forAllNoShrink[A1,A2,A3,A4,A5,A6,P]( + f: (A1,A2,A3,A4,A5,A6) => P)(implicit + pv: P => Prop, + a1: Arbitrary[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], pp4: A4 => Pretty, + a5: Arbitrary[A5], pp5: A5 => Pretty, + a6: Arbitrary[A6], pp6: A6 => Pretty + ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4], arbitrary[A5], arbitrary[A6])(f) + + /** Converts a function into a universally quantified property */ + def forAllNoShrink[A1,A2,A3,A4,A5,A6,A7,P]( + f: (A1,A2,A3,A4,A5,A6,A7) => P)(implicit + pv: P => Prop, + a1: Arbitrary[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], pp4: A4 => Pretty, + a5: Arbitrary[A5], pp5: A5 => Pretty, + a6: Arbitrary[A6], pp6: A6 => Pretty, + a7: Arbitrary[A7], pp7: A7 => Pretty + ): Prop = { + forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4], arbitrary[A5], arbitrary[A6], + arbitrary[A7])(f) + } + + /** Converts a function into a universally quantified property */ + def forAllNoShrink[A1,A2,A3,A4,A5,A6,A7,A8,P]( + f: (A1,A2,A3,A4,A5,A6,A7,A8) => P)(implicit + pv: P => Prop, + a1: Arbitrary[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], pp4: A4 => Pretty, + a5: Arbitrary[A5], pp5: A5 => Pretty, + a6: Arbitrary[A6], pp6: A6 => Pretty, + a7: Arbitrary[A7], pp7: A7 => Pretty, + a8: Arbitrary[A8], pp8: A8 => Pretty + ): Prop = { + forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4], arbitrary[A5], arbitrary[A6], + arbitrary[A7], arbitrary[A8])(f) + } + + /** Universal quantifier for an explicit generator. Shrinks failed arguments + * with the given shrink function */ + def forAllShrink[T, P](g: Gen[T], + shrink: T => Stream[T])(f: T => P + )(implicit pv: P => Prop, pp: T => Pretty + ): Prop = Prop { prms => + + val gr = g.doApply(prms) + val labels = gr.labels.mkString(",") + + def result(x: T) = { + val p = secure(pv(f(x))) + provedToTrue(p(prms)) + } + + /** Returns the first failed result in Left or success in Right */ + def getFirstFailure(xs: Stream[T]): Either[(T,Result),(T,Result)] = { + assert(!xs.isEmpty, "Stream cannot be empty") + val results = xs.map(x => (x, result(x))) + results.dropWhile(!_._2.failure).headOption match { + case None => Right(results.head) + case Some(xr) => Left(xr) + } + } + + def shrinker(x: T, r: Result, shrinks: Int, orig: T): Result = { + val xs = shrink(x).filter(gr.sieve) + val res = r.addArg(Arg(labels,x,shrinks,orig,pp(x),pp(orig))) + if(xs.isEmpty) res else getFirstFailure(xs) match { + case Right((x2,r2)) => res + case Left((x2,r2)) => shrinker(x2, replOrig(r,r2), shrinks+1, orig) + } + } + + def replOrig(r0: Result, r1: Result) = (r0.args,r1.args) match { + case (a0::_,a1::as) => + r1.copy( + args = a1.copy( + origArg = a0.origArg, + prettyOrigArg = a0.prettyOrigArg + ) :: as + ) + case _ => r1 + } + + gr.retrieve match { + case None => undecided(prms) + case Some(x) => + val r = result(x) + if (!r.failure) r.addArg(Arg(labels,x,0,x,pp(x),pp(x))) + else shrinker(x,r,0,x) + } + + } + + /** Universal quantifier for an explicit generator. Shrinks failed arguments + * with the default shrink function for the type */ + def forAll[T1,P]( + g1: Gen[T1])( + f: T1 => P)(implicit + p: P => Prop, + s1: Shrink[T1], + pp1: T1 => Pretty + ): Prop = forAllShrink[T1,P](g1, shrink[T1])(f) + + /** Universal quantifier for two explicit generators. Shrinks failed arguments + * with the default shrink function for the type */ + def forAll[T1,T2,P]( + g1: Gen[T1], g2: Gen[T2])( + f: (T1,T2) => P)(implicit + p: P => Prop, + s1: Shrink[T1], pp1: T1 => Pretty, + s2: Shrink[T2], pp2: T2 => Pretty + ): Prop = forAll(g1)(t => forAll(g2)(f(t, _:T2))) + + /** Universal quantifier for three explicit generators. Shrinks failed arguments + * with the default shrink function for the type */ + def forAll[T1,T2,T3,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3])( + f: (T1,T2,T3) => P)(implicit + p: P => Prop, + s1: Shrink[T1], pp1: T1 => Pretty, + s2: Shrink[T2], pp2: T2 => Pretty, + s3: Shrink[T3], pp3: T3 => Pretty + ): Prop = forAll(g1)(t => forAll(g2,g3)(f(t, _:T2, _:T3))) + + /** Universal quantifier for four explicit generators. Shrinks failed arguments + * with the default shrink function for the type */ + def forAll[T1,T2,T3,T4,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4])( + f: (T1,T2,T3,T4) => P)(implicit + p: P => Prop, + s1: Shrink[T1], pp1: T1 => Pretty, + s2: Shrink[T2], pp2: T2 => Pretty, + s3: Shrink[T3], pp3: T3 => Pretty, + s4: Shrink[T4], pp4: T4 => Pretty + ): Prop = forAll(g1)(t => forAll(g2,g3,g4)(f(t, _:T2, _:T3, _:T4))) + + /** Universal quantifier for five explicit generators. Shrinks failed arguments + * with the default shrink function for the type */ + def forAll[T1,T2,T3,T4,T5,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5])( + f: (T1,T2,T3,T4,T5) => P)(implicit + p: P => Prop, + s1: Shrink[T1], pp1: T1 => Pretty, + s2: Shrink[T2], pp2: T2 => Pretty, + s3: Shrink[T3], pp3: T3 => Pretty, + s4: Shrink[T4], pp4: T4 => Pretty, + s5: Shrink[T5], pp5: T5 => Pretty + ): Prop = forAll(g1)(t => forAll(g2,g3,g4,g5)(f(t, _:T2, _:T3, _:T4, _:T5))) + + /** Universal quantifier for six explicit generators. Shrinks failed arguments + * with the default shrink function for the type */ + def forAll[T1,T2,T3,T4,T5,T6,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6])( + f: (T1,T2,T3,T4,T5,T6) => P)(implicit + p: P => Prop, + s1: Shrink[T1], pp1: T1 => Pretty, + s2: Shrink[T2], pp2: T2 => Pretty, + s3: Shrink[T3], pp3: T3 => Pretty, + s4: Shrink[T4], pp4: T4 => Pretty, + s5: Shrink[T5], pp5: T5 => Pretty, + s6: Shrink[T6], pp6: T6 => Pretty + ): Prop = forAll(g1)(t => forAll(g2,g3,g4,g5,g6)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6))) + + /** Universal quantifier for seven explicit generators. Shrinks failed arguments + * with the default shrink function for the type */ + def forAll[T1,T2,T3,T4,T5,T6,T7,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7])( + f: (T1,T2,T3,T4,T5,T6,T7) => P)(implicit + p: P => Prop, + s1: Shrink[T1], pp1: T1 => Pretty, + s2: Shrink[T2], pp2: T2 => Pretty, + s3: Shrink[T3], pp3: T3 => Pretty, + s4: Shrink[T4], pp4: T4 => Pretty, + s5: Shrink[T5], pp5: T5 => Pretty, + s6: Shrink[T6], pp6: T6 => Pretty, + s7: Shrink[T7], pp7: T7 => Pretty + ): Prop = forAll(g1)(t => forAll(g2,g3,g4,g5,g6,g7)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7))) + + /** Universal quantifier for eight explicit generators. Shrinks failed arguments + * with the default shrink function for the type */ + def forAll[T1,T2,T3,T4,T5,T6,T7,T8,P]( + g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7], g8: Gen[T8])( + f: (T1,T2,T3,T4,T5,T6,T7,T8) => P)(implicit + p: P => Prop, + s1: Shrink[T1], pp1: T1 => Pretty, + s2: Shrink[T2], pp2: T2 => Pretty, + s3: Shrink[T3], pp3: T3 => Pretty, + s4: Shrink[T4], pp4: T4 => Pretty, + s5: Shrink[T5], pp5: T5 => Pretty, + s6: Shrink[T6], pp6: T6 => Pretty, + s7: Shrink[T7], pp7: T7 => Pretty, + s8: Shrink[T8], pp8: T8 => Pretty + ): Prop = forAll(g1)(t => forAll(g2,g3,g4,g5,g6,g7,g8)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7, _:T8))) + + /** Converts a function into a universally quantified property */ + def forAll[A1,P] ( + f: A1 => P)(implicit + p: P => Prop, + a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty + ): Prop = forAllShrink(arbitrary[A1],shrink[A1])(f andThen p) + + /** Converts a function into a universally quantified property */ + def forAll[A1,A2,P] ( + f: (A1,A2) => P)(implicit + p: P => Prop, + a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty + ): Prop = forAll((a: A1) => forAll(f(a, _:A2))) + + /** Converts a function into a universally quantified property */ + def forAll[A1,A2,A3,P] ( + f: (A1,A2,A3) => P)(implicit + p: P => Prop, + a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty + ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3))) + + /** Converts a function into a universally quantified property */ + def forAll[A1,A2,A3,A4,P] ( + f: (A1,A2,A3,A4) => P)(implicit + p: P => Prop, + a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty + ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4))) + + /** Converts a function into a universally quantified property */ + def forAll[A1,A2,A3,A4,A5,P] ( + f: (A1,A2,A3,A4,A5) => P)(implicit + p: P => Prop, + a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty, + a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty + ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4, _:A5))) + + /** Converts a function into a universally quantified property */ + def forAll[A1,A2,A3,A4,A5,A6,P] ( + f: (A1,A2,A3,A4,A5,A6) => P)(implicit + p: P => Prop, + a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty, + a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty, + a6: Arbitrary[A6], s6: Shrink[A6], pp6: A6 => Pretty + ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4, _:A5, _:A6))) + + /** Converts a function into a universally quantified property */ + def forAll[A1,A2,A3,A4,A5,A6,A7,P] ( + f: (A1,A2,A3,A4,A5,A6,A7) => P)(implicit + p: P => Prop, + a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty, + a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty, + a6: Arbitrary[A6], s6: Shrink[A6], pp6: A6 => Pretty, + a7: Arbitrary[A7], s7: Shrink[A7], pp7: A7 => Pretty + ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4, _:A5, _:A6, _:A7))) + + /** Converts a function into a universally quantified property */ + def forAll[A1,A2,A3,A4,A5,A6,A7,A8,P] ( + f: (A1,A2,A3,A4,A5,A6,A7,A8) => P)(implicit + p: P => Prop, + a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty, + a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty, + a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty, + a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty, + a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty, + a6: Arbitrary[A6], s6: Shrink[A6], pp6: A6 => Pretty, + a7: Arbitrary[A7], s7: Shrink[A7], pp7: A7 => Pretty, + a8: Arbitrary[A8], s8: Shrink[A8], pp8: A8 => Pretty + ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4, _:A5, _:A6, _:A7, _:A8))) + + /** Ensures that the property expression passed in completes within the given + * space of time. */ + def within(maximumMs: Long)(wrappedProp: => Prop): Prop = new Prop { + @tailrec private def attempt(prms: Parameters, endTime: Long): Result = { + val result = wrappedProp.apply(prms) + if (System.currentTimeMillis > endTime) { + (if(result.failure) result else Result(status = False)).label("Timeout") + } else { + if (result.success) result + else attempt(prms, endTime) + } + } + def apply(prms: Parameters) = attempt(prms, System.currentTimeMillis + maximumMs) + } +} diff --git a/src/partest-extras/scala/org/scalacheck/Properties.scala b/src/partest-extras/scala/org/scalacheck/Properties.scala new file mode 100644 index 000000000000..abaac61c7f09 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/Properties.scala @@ -0,0 +1,82 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +import util.ConsoleReporter + +/** Represents a collection of properties, with convenient methods + * for checking all properties at once. This class is itself a property, which + * holds if and only if all of the contained properties hold. + *

Properties are added in the following way:

+ * + * {{{ + * object MyProps extends Properties("MyProps") { + * property("myProp1") = forAll { (n:Int, m:Int) => + * n+m == m+n + * } + * } + * }}} + */ +class Properties(val name: String) extends Prop { + + private val props = new scala.collection.mutable.ListBuffer[(String,Prop)] + + /** Returns one property which holds if and only if all of the + * properties in this property collection hold */ + private def oneProperty: Prop = Prop.all((properties map (_._2)):_*) + + /** Returns all properties of this collection in a list of name/property + * pairs. */ + def properties: Seq[(String,Prop)] = props + + def apply(p: Gen.Parameters) = oneProperty(p) + + /** Convenience method that checks the properties with the given parameters + * and reports the result on the console. If you need to get the results + * from the test use the `check` methods in [[org.scalacheck.Test]] + * instead. */ + override def check(prms: Test.Parameters): Unit = Test.checkProperties( + prms.withTestCallback(ConsoleReporter(1) chain prms.testCallback), this + ) + + /** Convenience method that checks the properties and reports the + * result on the console. If you need to get the results from the test use + * the `check` methods in [[org.scalacheck.Test]] instead. */ + override def check: Unit = check(Test.Parameters.default) + + /** The logic for main, separated out to make it easier to + * avoid System.exit calls. Returns exit code. + */ + override def mainRunner(args: Array[String]): Int = { + Test.parseParams(args) match { + case Some(params) => + val res = Test.checkProperties(params, this) + val failed = res.filter(!_._2.passed).size + failed + case None => + println("Incorrect options") + -1 + } + } + + /** Adds all properties from another property collection to this one. */ + def include(ps: Properties) = for((n,p) <- ps.properties) property(n) = p + + /** Used for specifying properties. Usage: + * {{{ + * property("myProp") = ... + * }}} + */ + class PropertySpecifier() { + def update(propName: String, p: Prop) = props += ((name+"."+propName, p)) + } + + lazy val property = new PropertySpecifier() +} diff --git a/src/partest-extras/scala/org/scalacheck/ScalaCheckFramework.scala b/src/partest-extras/scala/org/scalacheck/ScalaCheckFramework.scala new file mode 100644 index 000000000000..754b67764de3 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/ScalaCheckFramework.scala @@ -0,0 +1,93 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +import util.Pretty + +import org.scalatools.testing._ + +class ScalaCheckFramework extends Framework { + + private def mkFP(mod: Boolean, cname: String) = + new SubclassFingerprint { + val superClassName = cname + val isModule = mod + } + + val name = "ScalaCheck" + + val tests = Array[Fingerprint]( + mkFP(true, "org.scalacheck.Properties"), + mkFP(false, "org.scalacheck.Prop"), + mkFP(false, "org.scalacheck.Properties"), + mkFP(true, "org.scalacheck.Prop") + ) + + def testRunner(loader: ClassLoader, loggers: Array[Logger]) = new Runner2 { + + private def asEvent(nr: (String, Test.Result)) = nr match { + case (n: String, r: Test.Result) => new Event { + val testName = n + val description = n + val result = r.status match { + case Test.Passed => Result.Success + case _:Test.Proved => Result.Success + case _:Test.Failed => Result.Failure + case Test.Exhausted => Result.Skipped + case _:Test.PropException | _:Test.GenException => Result.Error + } + val error = r.status match { + case Test.PropException(_, e, _) => e + case _:Test.Failed => new Exception(Pretty.pretty(r,Pretty.Params(0))) + case _ => null + } + } + } + + def run(testClassName: String, fingerprint: Fingerprint, handler: EventHandler, args: Array[String]) { + + val testCallback = new Test.TestCallback { + override def onPropEval(n: String, w: Int, s: Int, d: Int) = {} + + override def onTestResult(n: String, r: Test.Result) = { + for (l <- loggers) { + import Pretty._ + val verbosityOpts = Set("-verbosity", "-v") + val verbosity = args.grouped(2).filter(twos => verbosityOpts(twos.head)).toSeq.headOption.map(_.last).map(_.toInt).getOrElse(0) + l.info( + (if (r.passed) "+ " else "! ") + n + ": " + pretty(r, Params(verbosity)) + ) + } + handler.handle(asEvent((n,r))) + } + } + + val prms = Test.parseParams(args) match { + case Some(params) => + params.withTestCallback(testCallback).withCustomClassLoader(Some(loader)) + // TODO: Maybe handle this a bit better than throwing exception? + case None => throw new Exception() + } + + fingerprint match { + case fp: SubclassFingerprint => + val obj = + if(fp.isModule) Class.forName(testClassName + "$", true, loader).getField("MODULE$").get(null) + else Class.forName(testClassName, true, loader).newInstance + if(obj.isInstanceOf[Properties]) + Test.checkProperties(prms, obj.asInstanceOf[Properties]) + else + handler.handle(asEvent((testClassName, Test.check(prms, obj.asInstanceOf[Prop])))) + } + } + + } + +} diff --git a/src/partest-extras/scala/org/scalacheck/Shrink.scala b/src/partest-extras/scala/org/scalacheck/Shrink.scala new file mode 100644 index 000000000000..8ec28f4c4b28 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/Shrink.scala @@ -0,0 +1,215 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +import util.{Buildable,Buildable2} +import scala.collection.{ JavaConversions => jcl } + +sealed abstract class Shrink[T] { + def shrink(x: T): Stream[T] +} + +object Shrink { + + import Stream.{cons, empty} + import scala.collection._ + import java.util.ArrayList + + /** Interleaves two streams */ + private def interleave[T](xs: Stream[T], ys: Stream[T]): Stream[T] = + if(xs.isEmpty) ys + else if(ys.isEmpty) xs + else cons(xs.head, cons(ys.head, interleave(xs.tail, ys.tail))) + + /** Shrink instance factory */ + def apply[T](s: T => Stream[T]): Shrink[T] = new Shrink[T] { + override def shrink(x: T) = s(x) + } + + /** Shrink a value */ + def shrink[T](x: T)(implicit s: Shrink[T]): Stream[T] = s.shrink(x) + + /** Default shrink instance */ + implicit def shrinkAny[T]: Shrink[T] = Shrink(x => empty) + + /** Shrink instance of container */ + implicit def shrinkContainer[C[_],T](implicit v: C[T] => Traversable[T], s: Shrink[T], + b: Buildable[T,C] + ): Shrink[C[T]] = Shrink { xs: C[T] => + val ys = v(xs) + val zs = ys.toStream + removeChunks(ys.size,zs).append(shrinkOne(zs)).map(b.fromIterable) + } + + /** Shrink instance of container2 */ + implicit def shrinkContainer2[C[_,_],T,U](implicit v: C[T,U] => Traversable[(T,U)], s: Shrink[(T,U)], + b: Buildable2[T,U,C] + ): Shrink[C[T,U]] = Shrink { xs: C[T,U] => + val ys = v(xs) + val zs = ys.toStream + removeChunks(ys.size,zs).append(shrinkOne(zs)).map(b.fromIterable) + } + + private def removeChunks[T](n: Int, xs: Stream[T]): Stream[Stream[T]] = + if (xs.isEmpty) empty + else if (xs.tail.isEmpty) cons(empty, empty) + else { + val n1 = n / 2 + val n2 = n - n1 + lazy val xs1 = xs.take(n1) + lazy val xs2 = xs.drop(n1) + lazy val xs3 = + for (ys1 <- removeChunks(n1, xs1) if !ys1.isEmpty) yield ys1 append xs2 + lazy val xs4 = + for (ys2 <- removeChunks(n2, xs2) if !ys2.isEmpty) yield xs1 append ys2 + + cons(xs1, cons(xs2, interleave(xs3, xs4))) + } + + private def shrinkOne[T : Shrink](zs: Stream[T]): Stream[Stream[T]] = + if (zs.isEmpty) empty + else { + val x = zs.head + val xs = zs.tail + shrink(x).map(cons(_,xs)).append(shrinkOne(xs).map(cons(x,_))) + } + + /** Shrink instance of integer */ + implicit lazy val shrinkInt: Shrink[Int] = Shrink { n => + + def halfs(n: Int): Stream[Int] = + if(n == 0) empty else cons(n, halfs(n/2)) + + if(n == 0) empty else { + val ns = halfs(n/2).map(n - _) + cons(0, interleave(ns, ns.map(-1 * _))) + } + } + + /** Shrink instance of String */ + implicit lazy val shrinkString: Shrink[String] = Shrink { s => + shrinkContainer[List,Char].shrink(s.toList).map(_.mkString) + } + + /** Shrink instance of Option */ + implicit def shrinkOption[T : Shrink]: Shrink[Option[T]] = Shrink { + case None => empty + case Some(x) => cons(None, for(y <- shrink(x)) yield Some(y)) + } + + /** Shrink instance of 2-tuple */ + implicit def shrinkTuple2[ + T1:Shrink, T2:Shrink + ]: Shrink[(T1,T2)] = + Shrink { case (t1,t2) => + shrink(t1).map((_,t2)) append + shrink(t2).map((t1,_)) + } + + /** Shrink instance of 3-tuple */ + implicit def shrinkTuple3[ + T1:Shrink, T2:Shrink, T3:Shrink + ]: Shrink[(T1,T2,T3)] = + Shrink { case (t1,t2,t3) => + shrink(t1).map((_, t2, t3)) append + shrink(t2).map((t1, _, t3)) append + shrink(t3).map((t1, t2, _)) + } + + /** Shrink instance of 4-tuple */ + implicit def shrinkTuple4[ + T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink + ]: Shrink[(T1,T2,T3,T4)] = + Shrink { case (t1,t2,t3,t4) => + shrink(t1).map((_, t2, t3, t4)) append + shrink(t2).map((t1, _, t3, t4)) append + shrink(t3).map((t1, t2, _, t4)) append + shrink(t4).map((t1, t2, t3, _)) + } + + /** Shrink instance of 5-tuple */ + implicit def shrinkTuple5[ + T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink + ]: Shrink[(T1,T2,T3,T4,T5)] = + Shrink { case (t1,t2,t3,t4,t5) => + shrink(t1).map((_, t2, t3, t4, t5)) append + shrink(t2).map((t1, _, t3, t4, t5)) append + shrink(t3).map((t1, t2, _, t4, t5)) append + shrink(t4).map((t1, t2, t3, _, t5)) append + shrink(t5).map((t1, t2, t3, t4, _)) + } + + /** Shrink instance of 6-tuple */ + implicit def shrinkTuple6[ + T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink + ]: Shrink[(T1,T2,T3,T4,T5,T6)] = + Shrink { case (t1,t2,t3,t4,t5,t6) => + shrink(t1).map((_, t2, t3, t4, t5, t6)) append + shrink(t2).map((t1, _, t3, t4, t5, t6)) append + shrink(t3).map((t1, t2, _, t4, t5, t6)) append + shrink(t4).map((t1, t2, t3, _, t5, t6)) append + shrink(t5).map((t1, t2, t3, t4, _, t6)) append + shrink(t6).map((t1, t2, t3, t4, t5, _)) + } + + /** Shrink instance of 7-tuple */ + implicit def shrinkTuple7[ + T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink, T7:Shrink + ]: Shrink[(T1,T2,T3,T4,T5,T6,T7)] = + Shrink { case (t1,t2,t3,t4,t5,t6,t7) => + shrink(t1).map((_, t2, t3, t4, t5, t6, t7)) append + shrink(t2).map((t1, _, t3, t4, t5, t6, t7)) append + shrink(t3).map((t1, t2, _, t4, t5, t6, t7)) append + shrink(t4).map((t1, t2, t3, _, t5, t6, t7)) append + shrink(t5).map((t1, t2, t3, t4, _, t6, t7)) append + shrink(t6).map((t1, t2, t3, t4, t5, _, t7)) append + shrink(t7).map((t1, t2, t3, t4, t5, t6, _)) + } + + /** Shrink instance of 8-tuple */ + implicit def shrinkTuple8[ + T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink, + T7:Shrink, T8:Shrink + ]: Shrink[(T1,T2,T3,T4,T5,T6,T7,T8)] = + Shrink { case (t1,t2,t3,t4,t5,t6,t7,t8) => + shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8)) append + shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8)) append + shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8)) append + shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8)) append + shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8)) append + shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8)) append + shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8)) append + shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _)) + } + + /** Shrink instance of 9-tuple */ + implicit def shrinkTuple9[ + T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink, + T7:Shrink, T8:Shrink, T9:Shrink + ]: Shrink[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] = + Shrink { case (t1,t2,t3,t4,t5,t6,t7,t8,t9) => + shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8, t9)) append + shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8, t9)) append + shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8, t9)) append + shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8, t9)) append + shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8, t9)) append + shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8, t9)) append + shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8, t9)) append + shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _, t9)) append + shrink(t9).map((t1, t2, t3, t4, t5, t6, t7, t8, _)) + } + + /** Transform a Shrink[T] to a Shrink[U] where T and U are two isomorphic types + * whose relationship is described by the provided transformation functions. + * (exponential functor map) */ + def xmap[T, U](from: T => U, to: U => T)(implicit st: Shrink[T]): Shrink[U] = Shrink[U] { u: U ⇒ + st.shrink(to(u)).map(from) + } +} diff --git a/src/partest-extras/scala/org/scalacheck/Test.scala b/src/partest-extras/scala/org/scalacheck/Test.scala new file mode 100644 index 000000000000..9a9c62b93f94 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/Test.scala @@ -0,0 +1,372 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck + +import Prop.Arg + +object Test { + + import util.{FreqMap, ConsoleReporter} + + /** Test parameters used by the check methods. Default + * parameters are defined by [[Test.Parameters.Default]]. */ + trait Parameters { + /** The minimum number of tests that must succeed for ScalaCheck to + * consider a property passed. */ + val minSuccessfulTests: Int + + /** Create a copy of this [[Test.Parameters]] instance with + * [[Test.Parameters.minSuccessfulTests]] set to the specified value. */ + def withMinSuccessfulTests(minSuccessfulTests: Int): Parameters = cp( + minSuccessfulTests = minSuccessfulTests + ) + + /** The starting size given as parameter to the generators. */ + val minSize: Int + + /** Create a copy of this [[Test.Parameters]] instance with + * [[Test.Parameters.minSize]] set to the specified value. */ + def withMinSize(minSize: Int): Parameters = cp( + minSize = minSize + ) + + /** The maximum size given as parameter to the generators. */ + val maxSize: Int + + /** Create a copy of this [[Test.Parameters]] instance with + * [[Test.Parameters.maxSize]] set to the specified value. */ + def withMaxSize(maxSize: Int): Parameters = cp( + maxSize = maxSize + ) + + /** The random number generator used. */ + val rng: scala.util.Random + + /** Create a copy of this [[Test.Parameters]] instance with + * [[Test.Parameters.rng]] set to the specified value. */ + def withRng(rng: scala.util.Random): Parameters = cp( + rng = rng + ) + + /** The number of tests to run in parallel. */ + val workers: Int + + /** Create a copy of this [[Test.Parameters]] instance with + * [[Test.Parameters.workers]] set to the specified value. */ + def withWorkers(workers: Int): Parameters = cp( + workers = workers + ) + + /** A callback that ScalaCheck calls each time a test is executed. */ + val testCallback: TestCallback + + /** Create a copy of this [[Test.Parameters]] instance with + * [[Test.Parameters.testCallback]] set to the specified value. */ + def withTestCallback(testCallback: TestCallback): Parameters = cp( + testCallback = testCallback + ) + + /** The maximum ratio between discarded and passed tests allowed before + * ScalaCheck gives up and discards the property. At least + * `minSuccesfulTests` will always be run, though. */ + val maxDiscardRatio: Float + + /** Create a copy of this [[Test.Parameters]] instance with + * [[Test.Parameters.maxDiscardRatio]] set to the specified value. */ + def withMaxDiscardRatio(maxDiscardRatio: Float): Parameters = cp( + maxDiscardRatio = maxDiscardRatio + ) + + /** A custom class loader that should be used during test execution. */ + val customClassLoader: Option[ClassLoader] + + /** Create a copy of this [[Test.Parameters]] instance with + * [[Test.Parameters.customClassLoader]] set to the specified value. */ + def withCustomClassLoader(customClassLoader: Option[ClassLoader] + ): Parameters = cp( + customClassLoader = customClassLoader + ) + + // private since we can't guarantee binary compatibility for this one + private case class cp( + minSuccessfulTests: Int = minSuccessfulTests, + minSize: Int = minSize, + maxSize: Int = maxSize, + rng: scala.util.Random = rng, + workers: Int = workers, + testCallback: TestCallback = testCallback, + maxDiscardRatio: Float = maxDiscardRatio, + customClassLoader: Option[ClassLoader] = customClassLoader + ) extends Parameters + } + + /** Test parameters used by the check methods. Default + * parameters are defined by [[Test.Parameters.Default]]. */ + object Parameters { + /** Default test parameters trait. This can be overriden if you need to + * tweak the parameters: + * + * {{{ + * val myParams = new Parameters.Default { + * override val minSuccesfulTests = 600 + * override val maxDiscardRatio = 8 + * } + * }}} + * + * You can also use the withXXX-methods in + * [[org.scalacheck.Test.Parameters]] to achieve + * the same thing: + * + * {{{ + * val myParams = Parameters.default + * .withMinSuccessfulTests(600) + * .withMaxDiscardRatio(8) + * }}} */ + trait Default extends Parameters { + val minSuccessfulTests: Int = 100 + val minSize: Int = 0 + val maxSize: Int = Gen.Parameters.default.size + val rng: scala.util.Random = Gen.Parameters.default.rng + val workers: Int = 1 + val testCallback: TestCallback = new TestCallback {} + val maxDiscardRatio: Float = 5 + val customClassLoader: Option[ClassLoader] = None + } + + /** Default test parameters instance. */ + val default: Parameters = new Default {} + + /** Verbose console reporter test parameters instance. */ + val defaultVerbose: Parameters = new Default { + override val testCallback = ConsoleReporter(2) + } + } + + /** Test statistics */ + case class Result( + status: Status, + succeeded: Int, + discarded: Int, + freqMap: FreqMap[Set[Any]], + time: Long = 0 + ) { + def passed = status match { + case Passed => true + case Proved(_) => true + case _ => false + } + } + + /** Test status */ + sealed trait Status + + /** ScalaCheck found enough cases for which the property holds, so the + * property is considered correct. (It is not proved correct, though). */ + case object Passed extends Status + + /** ScalaCheck managed to prove the property correct */ + sealed case class Proved(args: List[Arg[Any]]) extends Status + + /** The property was proved wrong with the given concrete arguments. */ + sealed case class Failed(args: List[Arg[Any]], labels: Set[String]) extends Status + + /** The property test was exhausted, it wasn't possible to generate enough + * concrete arguments satisfying the preconditions to get enough passing + * property evaluations. */ + case object Exhausted extends Status + + /** An exception was raised when trying to evaluate the property with the + * given concrete arguments. If an exception was raised before or during + * argument generation, the argument list will be empty. */ + sealed case class PropException(args: List[Arg[Any]], e: Throwable, + labels: Set[String]) extends Status + + /** An exception was raised when trying to generate concrete arguments + * for evaluating the property. + * @deprecated Not used. The type PropException is used for all exceptions. + */ + @deprecated("Not used. The type PropException is used for all exceptions.", "1.11.2") + sealed case class GenException(e: Throwable) extends Status + + trait TestCallback { self => + /** Called each time a property is evaluated */ + def onPropEval(name: String, threadIdx: Int, succeeded: Int, + discarded: Int): Unit = () + + /** Called whenever a property has finished testing */ + def onTestResult(name: String, result: Result): Unit = () + + def chain(testCallback: TestCallback) = new TestCallback { + override def onPropEval(name: String, threadIdx: Int, + succeeded: Int, discarded: Int + ): Unit = { + self.onPropEval(name,threadIdx,succeeded,discarded) + testCallback.onPropEval(name,threadIdx,succeeded,discarded) + } + + override def onTestResult(name: String, result: Result): Unit = { + self.onTestResult(name,result) + testCallback.onTestResult(name,result) + } + } + } + + private def assertParams(prms: Parameters) = { + import prms._ + if( + minSuccessfulTests <= 0 || + maxDiscardRatio <= 0 || + minSize < 0 || + maxSize < minSize || + workers <= 0 + ) throw new IllegalArgumentException("Invalid test parameters") + } + + private def secure[T](x: => T): Either[T,Throwable] = + try { Left(x) } catch { case e: Throwable => Right(e) } + + def parseParams(args: Array[String]): Option[Parameters] = { + var params = Parameters.default + args.grouped(2).filter(_.size > 1).map(a => (a(0), a(1))).foreach { + case ("-workers" | "-w", n) => params = params.withWorkers(n.toInt) + case ("-minSize" | "-n", n) => params = params.withMinSize(n.toInt) + case ("-maxSize" | "-x", n) => params = params.withMaxSize(n.toInt) + case ("-verbosity" | "-v", n) => params = params.withTestCallback(ConsoleReporter(n.toInt)) + case ("-maxDiscardRatio" | "-r", n) => params = params.withMaxDiscardRatio(n.toFloat) + case ("-minSuccessfulTests" | "-s", n) => params = params.withMinSuccessfulTests(n.toInt) + case _ => + } + Some(params) + } + + /** Tests a property with parameters that are calculated by applying + * the provided function to [[Test.Parameters.default]]. + * Example use: + * + * {{{ + * Test.check(p) { _. + * withMinSuccessfulTests(80000). + * withWorkers(4) + * } + * }}} + */ + def check(p: Prop)(f: Parameters => Parameters): Result = + check(f(Parameters.default), p) + + /** Tests a property with the given testing parameters, and returns + * the test results. */ + def check(params: Parameters, p: Prop): Result = { + import params._ + import concurrent._ + + assertParams(params) + if(workers > 1) { + assert(!p.isInstanceOf[Commands], "Commands cannot be checked multi-threaded") + } + + val iterations = math.ceil(minSuccessfulTests / (workers: Double)) + val sizeStep = (maxSize-minSize) / (iterations*workers) + var stop = false + val genPrms = new Gen.Parameters.Default { override val rng = params.rng } + val tp = java.util.concurrent.Executors.newFixedThreadPool(workers) + implicit val ec = ExecutionContext.fromExecutor(tp) + + def workerFun(workerIdx: Int): Result = { + var n = 0 // passed tests + var d = 0 // discarded tests + var res: Result = null + var fm = FreqMap.empty[Set[Any]] + while(!stop && res == null && n < iterations) { + val size = (minSize: Double) + (sizeStep * (workerIdx + (workers*(n+d)))) + val propRes = p(genPrms.withSize(size.round.toInt)) + fm = if(propRes.collected.isEmpty) fm else fm + propRes.collected + propRes.status match { + case Prop.Undecided => + d += 1 + testCallback.onPropEval("", workerIdx, n, d) + // The below condition is kind of hacky. We have to have + // some margin, otherwise workers might stop testing too + // early because they have been exhausted, but the overall + // test has not. + if (n+d > minSuccessfulTests && 1+workers*maxDiscardRatio*n < d) + res = Result(Exhausted, n, d, fm) + case Prop.True => + n += 1 + testCallback.onPropEval("", workerIdx, n, d) + case Prop.Proof => + n += 1 + res = Result(Proved(propRes.args), n, d, fm) + stop = true + case Prop.False => + res = Result(Failed(propRes.args,propRes.labels), n, d, fm) + stop = true + case Prop.Exception(e) => + res = Result(PropException(propRes.args,e,propRes.labels), n, d, fm) + stop = true + } + } + if (res == null) { + if (maxDiscardRatio*n > d) Result(Passed, n, d, fm) + else Result(Exhausted, n, d, fm) + } else res + } + + def mergeResults(r1: Result, r2: Result): Result = { + val Result(st1, s1, d1, fm1, _) = r1 + val Result(st2, s2, d2, fm2, _) = r2 + if (st1 != Passed && st1 != Exhausted) + Result(st1, s1+s2, d1+d2, fm1++fm2, 0) + else if (st2 != Passed && st2 != Exhausted) + Result(st2, s1+s2, d1+d2, fm1++fm2, 0) + else { + if (s1+s2 >= minSuccessfulTests && maxDiscardRatio*(s1+s2) >= (d1+d2)) + Result(Passed, s1+s2, d1+d2, fm1++fm2, 0) + else + Result(Exhausted, s1+s2, d1+d2, fm1++fm2, 0) + } + } + + try { + val start = System.currentTimeMillis + val r = + if(workers < 2) workerFun(0) + else { + val fs = List.range(0,workers) map (idx => Future { + params.customClassLoader.map( + Thread.currentThread.setContextClassLoader(_) + ) + blocking { workerFun(idx) } + }) + val zeroRes = Result(Passed,0,0,FreqMap.empty[Set[Any]],0) + val res = Future.fold(fs)(zeroRes)(mergeResults) + Await.result(res, concurrent.duration.Duration.Inf) + } + val timedRes = r.copy(time = System.currentTimeMillis-start) + params.testCallback.onTestResult("", timedRes) + timedRes + } finally { + stop = true + tp.shutdown() + } + } + + /** Check a set of properties. */ + def checkProperties(prms: Parameters, ps: Properties): Seq[(String,Result)] = + ps.properties.map { case (name,p) => + val testCallback = new TestCallback { + override def onPropEval(n: String, t: Int, s: Int, d: Int) = + prms.testCallback.onPropEval(name,t,s,d) + override def onTestResult(n: String, r: Result) = + prms.testCallback.onTestResult(name,r) + } + val res = check(prms.withTestCallback(testCallback), p) + (name,res) + } +} diff --git a/src/partest-extras/scala/org/scalacheck/util/Buildable.scala b/src/partest-extras/scala/org/scalacheck/util/Buildable.scala new file mode 100644 index 000000000000..6a275b05c282 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/util/Buildable.scala @@ -0,0 +1,77 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck.util + +import collection._ + +trait Buildable[T,C[_]] { + def builder: mutable.Builder[T,C[T]] + def fromIterable(it: Traversable[T]): C[T] = { + val b = builder + b ++= it + b.result() + } +} + +trait Buildable2[T,U,C[_,_]] { + def builder: mutable.Builder[(T,U),C[T,U]] + def fromIterable(it: Traversable[(T,U)]): C[T,U] = { + val b = builder + b ++= it + b.result() + } +} + +object Buildable { + import generic.CanBuildFrom + + implicit def buildableCanBuildFrom[T, C[_]](implicit c: CanBuildFrom[C[_], T, C[T]]) = + new Buildable[T, C] { + def builder = c.apply + } + + import java.util.ArrayList + implicit def buildableArrayList[T] = new Buildable[T,ArrayList] { + def builder = new mutable.Builder[T,ArrayList[T]] { + val al = new ArrayList[T] + def +=(x: T) = { + al.add(x) + this + } + def clear() = al.clear() + def result() = al + } + } + +} + +object Buildable2 { + + implicit def buildableMutableMap[T,U] = new Buildable2[T,U,mutable.Map] { + def builder = mutable.Map.newBuilder + } + + implicit def buildableImmutableMap[T,U] = new Buildable2[T,U,immutable.Map] { + def builder = immutable.Map.newBuilder + } + + implicit def buildableMap[T,U] = new Buildable2[T,U,Map] { + def builder = Map.newBuilder + } + + implicit def buildableImmutableSortedMap[T: Ordering, U] = new Buildable2[T,U,immutable.SortedMap] { + def builder = immutable.SortedMap.newBuilder + } + + implicit def buildableSortedMap[T: Ordering, U] = new Buildable2[T,U,SortedMap] { + def builder = SortedMap.newBuilder + } + +} diff --git a/src/partest-extras/scala/org/scalacheck/util/CmdLineParser.scala b/src/partest-extras/scala/org/scalacheck/util/CmdLineParser.scala new file mode 100644 index 000000000000..45b6ac6948ee --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/util/CmdLineParser.scala @@ -0,0 +1,41 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck.util + +import scala.collection.Set +import org.scalacheck.Test + +private[scalacheck] trait CmdLineParser { + + type Elem = String + + trait Opt[+T] { + val default: T + val names: Set[String] + val help: String + } + trait Flag extends Opt[Unit] + trait IntOpt extends Opt[Int] + trait FloatOpt extends Opt[Float] + trait StrOpt extends Opt[String] + + class OptMap { + private val opts = new collection.mutable.HashMap[Opt[_], Any] + def apply(flag: Flag): Boolean = opts.contains(flag) + def apply[T](opt: Opt[T]): T = opts.get(opt) match { + case None => opt.default + case Some(v) => v.asInstanceOf[T] + } + def update[T](opt: Opt[T], optVal: T) = opts.update(opt, optVal) + } + + val opts: Set[Opt[_]] + +} diff --git a/src/partest-extras/scala/org/scalacheck/util/ConsoleReporter.scala b/src/partest-extras/scala/org/scalacheck/util/ConsoleReporter.scala new file mode 100644 index 000000000000..89858dfb64e1 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/util/ConsoleReporter.scala @@ -0,0 +1,44 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck.util + +import Pretty.{Params, pretty, format} +import org.scalacheck.{Prop, Properties, Test} + +/** A [[org.scalacheck.Test.TestCallback]] implementation that prints + * test results directly to the console. This is the callback used + * by ScalaCheck's command line test runner, and when you run [[org.scalacheck.Prop!.check:Unit*]] + */ +class ConsoleReporter(val verbosity: Int) extends Test.TestCallback { + + private val prettyPrms = Params(verbosity) + + override def onTestResult(name: String, res: Test.Result) = { + if(verbosity > 0) { + if(name == "") { + val s = (if(res.passed) "+ " else "! ") + pretty(res, prettyPrms) + printf("\r%s\n", format(s, "", "", 75)) + } else { + val s = (if(res.passed) "+ " else "! ") + name + ": " + + pretty(res, prettyPrms) + printf("\r%s\n", format(s, "", "", 75)) + } + } + } + +} + +object ConsoleReporter { + + /** Factory method, creates a ConsoleReporter with the + * the given verbosity */ + def apply(verbosity: Int = 0) = new ConsoleReporter(verbosity) + +} diff --git a/src/partest-extras/scala/org/scalacheck/util/FreqMap.scala b/src/partest-extras/scala/org/scalacheck/util/FreqMap.scala new file mode 100644 index 000000000000..2a9f36f1e540 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/util/FreqMap.scala @@ -0,0 +1,65 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck.util + +trait FreqMap[T] { + protected val underlying: scala.collection.immutable.Map[T,Int] + val total: Int + + def +(t: T) = new FreqMap[T] { + private val n = FreqMap.this.underlying.get(t) match { + case None => 1 + case Some(n) => n+1 + } + val underlying = FreqMap.this.underlying + (t -> n) + val total = FreqMap.this.total + 1 + } + + def -(t: T) = new FreqMap[T] { + val underlying = FreqMap.this.underlying.get(t) match { + case None => FreqMap.this.underlying + case Some(n) => FreqMap.this.underlying + (t -> (n-1)) + } + val total = FreqMap.this.total + 1 + } + + def ++(fm: FreqMap[T]) = new FreqMap[T] { + private val keys = FreqMap.this.underlying.keySet ++ fm.underlying.keySet + private val mappings = keys.toStream.map { x => + (x, fm.getCount(x).getOrElse(0) + FreqMap.this.getCount(x).getOrElse(0)) + } + val underlying = scala.collection.immutable.Map(mappings: _*) + val total = FreqMap.this.total + fm.total + } + + def --(fm: FreqMap[T]) = new FreqMap[T] { + val underlying = FreqMap.this.underlying transform { + case (x,n) => n - fm.getCount(x).getOrElse(0) + } + lazy val total = (0 /: underlying.valuesIterator) (_ + _) + } + + def getCount(t: T) = underlying.get(t) + + def getCounts: List[(T,Int)] = underlying.toList.sortBy(-_._2) + + def getRatio(t: T) = for(c <- getCount(t)) yield (c: Float)/total + + def getRatios = for((t,c) <- getCounts) yield (t, (c: Float)/total) + + override def toString = underlying.toString +} + +object FreqMap { + def empty[T] = new FreqMap[T] { + val underlying = scala.collection.immutable.Map.empty[T,Int] + val total = 0 + } +} diff --git a/src/partest-extras/scala/org/scalacheck/util/Pretty.scala b/src/partest-extras/scala/org/scalacheck/util/Pretty.scala new file mode 100644 index 000000000000..13a1b44b51d7 --- /dev/null +++ b/src/partest-extras/scala/org/scalacheck/util/Pretty.scala @@ -0,0 +1,129 @@ +/*-------------------------------------------------------------------------*\ +** ScalaCheck ** +** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. ** +** http://www.scalacheck.org ** +** ** +** This software is released under the terms of the Revised BSD License. ** +** There is NO WARRANTY. See the file LICENSE for the full text. ** +\*------------------------------------------------------------------------ */ + +package org.scalacheck.util + +import org.scalacheck.Prop.Arg +import org.scalacheck.Test + +import math.round + + +sealed trait Pretty { + def apply(prms: Pretty.Params): String + + def map(f: String => String) = Pretty(prms => f(Pretty.this(prms))) + + def flatMap(f: String => Pretty) = Pretty(prms => f(Pretty.this(prms))(prms)) +} + +object Pretty { + + case class Params(verbosity: Int) + + val defaultParams = Params(0) + + def apply(f: Params => String) = new Pretty { def apply(p: Params) = f(p) } + + def pretty[T <% Pretty](t: T, prms: Params): String = t(prms) + + def pretty[T <% Pretty](t: T): String = t(defaultParams) + + implicit def strBreak(s1: String) = new { + def /(s2: String) = if(s2 == "") s1 else s1+"\n"+s2 + } + + def pad(s: String, c: Char, length: Int) = + if(s.length >= length) s + else s + List.fill(length-s.length)(c).mkString + + def break(s: String, lead: String, length: Int): String = + if(s.length <= length) s + else s.substring(0, length) / break(lead+s.substring(length), lead, length) + + def format(s: String, lead: String, trail: String, width: Int) = + s.lines.map(l => break(lead+l+trail, " ", width)).mkString("\n") + + implicit def prettyAny(t: Any) = Pretty { p => t.toString } + + implicit def prettyString(t: String) = Pretty { p => "\""++t++"\"" } + + implicit def prettyList(l: List[Any]) = Pretty { p => + l.map("\""+_+"\"").mkString("List(", ", ", ")") + } + + implicit def prettyThrowable(e: Throwable) = Pretty { prms => + val strs = e.getStackTrace.map { st => + import st._ + getClassName+"."+getMethodName + "("+getFileName+":"+getLineNumber+")" + } + + val strs2 = + if(prms.verbosity <= 0) Array[String]() + else if(prms.verbosity <= 1) strs.take(5) + else strs + + e.getClass.getName + ": " + e.getMessage / strs2.mkString("\n") + } + + def prettyArgs(args: Seq[Arg[Any]]): Pretty = Pretty { prms => + if(args.isEmpty) "" else { + for((a,i) <- args.zipWithIndex) yield { + val l = "> "+(if(a.label == "") "ARG_"+i else a.label) + val s = + if(a.shrinks == 0) "" + else "\n"+l+"_ORIGINAL: "+a.prettyOrigArg(prms) + l+": "+a.prettyArg(prms)+""+s + } + }.mkString("\n") + } + + implicit def prettyFreqMap(fm: FreqMap[Set[Any]]) = Pretty { prms => + if(fm.total == 0) "" + else { + "> Collected test data: " / { + for { + (xs,r) <- fm.getRatios + ys = xs - (()) + if !ys.isEmpty + } yield round(r*100)+"% " + ys.mkString(", ") + }.mkString("\n") + } + } + + implicit def prettyTestRes(res: Test.Result) = Pretty { prms => + def labels(ls: collection.immutable.Set[String]) = + if(ls.isEmpty) "" + else "> Labels of failing property: " / ls.mkString("\n") + val s = res.status match { + case Test.Proved(args) => "OK, proved property."/prettyArgs(args)(prms) + case Test.Passed => "OK, passed "+res.succeeded+" tests." + case Test.Failed(args, l) => + "Falsified after "+res.succeeded+" passed tests."/labels(l)/prettyArgs(args)(prms) + case Test.Exhausted => + "Gave up after only "+res.succeeded+" passed tests. " + + res.discarded+" tests were discarded." + case Test.PropException(args,e,l) => + "Exception raised on property evaluation."/labels(l)/prettyArgs(args)(prms)/ + "> Exception: "+pretty(e,prms) + case Test.GenException(e) => + "Exception raised on argument generation."/ + "> Exception: "+pretty(e,prms) + } + val t = if(prms.verbosity <= 1) "" else "Elapsed time: "+prettyTime(res.time) + s/t/pretty(res.freqMap,prms) + } + + def prettyTime(millis: Long): String = { + val min = millis/(60*1000) + val sec = (millis-(60*1000*min)) / 1000d + if(min <= 0) "%.3f sec ".format(sec) + else "%d min %.3f sec ".format(min, sec) + } +} diff --git a/versions.properties b/versions.properties index 488535c9914f..3b8077ab885b 100644 --- a/versions.properties +++ b/versions.properties @@ -31,7 +31,9 @@ scala-asm.version=5.0.4-scala-3 # external modules, used internally (not shipped) partest.version.number=1.0.16 -scalacheck.version.number=1.11.6 +# We've embedded these sources in partest-extras for now. After 2.12.0 is released +# we can switch to a public release. +# scalacheck.version.number=1.11.6 # TODO: modularize the compiler #scala-compiler-doc.version.number=1.0.0-RC1 From 1ae80e868039e4e18843ec67768002085decb763 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 27 Jun 2016 13:44:52 +1000 Subject: [PATCH 111/153] Fix ParVector#padTo This was throwing a UnsupportedOperationError for small operations. The parallel collections test suite sets `-minSuccessfulTests 5` in test/files/scalacheck/parallel-collections/pc.scala, which is far lower thatn the default of 100, and means that we are less likely to falsify properties. This parameter seems to have been added in #2476, assuming I'm reading it correctly. Not sure of the motiviation, perhaps just to make the slowest part of the scalacheck test suite run faster? I haven't changed the paramater now, but instead have included a one element collection in generator. I also found that when the test failed, Scalacheck would try to minimize the example, but did so assuming that the elements of the tuple of test data could be independentally shrunk. This breaks the invariant that the two collections contain equal elements, and led to spurious error reports. I have disabled shrinking in all tests tests affected by this. --- .../parallel/immutable/package.scala | 7 ++- .../ParallelArrayCheck.scala | 2 +- .../ParallelArrayViewCheck.scala | 2 +- .../ParallelIterableCheck.scala | 44 +++++++++---------- .../ParallelMapCheck1.scala | 2 +- .../ParallelSeqCheck.scala | 33 +++++++------- .../ParallelSetCheck.scala | 2 +- 7 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/library/scala/collection/parallel/immutable/package.scala b/src/library/scala/collection/parallel/immutable/package.scala index 8fd84eaf4d5a..3cafdba5f702 100644 --- a/src/library/scala/collection/parallel/immutable/package.scala +++ b/src/library/scala/collection/parallel/immutable/package.scala @@ -20,7 +20,12 @@ package immutable { self => def apply(idx: Int) = if (0 <= idx && idx < length) elem else throw new IndexOutOfBoundsException("" + idx) - override def seq = throw new UnsupportedOperationException + override def seq: collection.immutable.Seq[T] = new collection.AbstractSeq[T] with collection.immutable.Seq[T] { + override def length: Int = self.length + override def apply(idx: Int): T = self.apply(idx) + override def iterator: Iterator[T] = Iterator.continually(elem).take(length) + override def par: ParSeq[T] = self + } def update(idx: Int, elem: T) = throw new UnsupportedOperationException class ParIterator(var i: Int = 0, val until: Int = length, elem: T = self.elem) extends SeqSplitter[T] { diff --git a/test/files/scalacheck/parallel-collections/ParallelArrayCheck.scala b/test/files/scalacheck/parallel-collections/ParallelArrayCheck.scala index 691a3e961eda..605c16857a40 100644 --- a/test/files/scalacheck/parallel-collections/ParallelArrayCheck.scala +++ b/test/files/scalacheck/parallel-collections/ParallelArrayCheck.scala @@ -44,7 +44,7 @@ abstract class ParallelArrayCheck[T](tp: String) extends ParallelSeqCheck[T]("Pa pa } - property("array mappings must be equal") = forAll(collectionPairs) { case (t, coll) => + property("array mappings must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => val results = for ((f, ind) <- mapFunctions.zipWithIndex) yield ("op index: " + ind) |: t.map(f) == coll.map(f) results.reduceLeft(_ && _) diff --git a/test/files/scalacheck/parallel-collections/ParallelArrayViewCheck.scala b/test/files/scalacheck/parallel-collections/ParallelArrayViewCheck.scala index 9805e2644f74..fb09a5bbb724 100644 --- a/test/files/scalacheck/parallel-collections/ParallelArrayViewCheck.scala +++ b/test/files/scalacheck/parallel-collections/ParallelArrayViewCheck.scala @@ -46,7 +46,7 @@ // pa.view // } -// property("forces must be equal") = forAll(collectionPairs) { case (s, coll) => +// property("forces must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) => // val smodif = (s ++ s).reverse.take(s.length).reverse.zip(s).drop(s.length / 2) // val cmodif = (coll ++ s).reverse.take(s.length).reverse.zip(s).drop(s.length / 2).force // smodif == cmodif diff --git a/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala b/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala index 468bcb6dd117..7e7ef2ce1bcd 100644 --- a/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala +++ b/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala @@ -109,7 +109,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col println("cf == tf - " + (cf == tf)) } - property("reductions must be equal for assoc. operators") = forAll(collectionPairs) { case (t, coll) => + property("reductions must be equal for assoc. operators") = forAllNoShrink(collectionPairs) { case (t, coll) => if (t.size != 0) { val results = for ((op, ind) <- reduceOperators.zipWithIndex) yield { val tr = t.reduceLeft(op) @@ -127,7 +127,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col } else "has size 0" |: true } - property("counts must be equal") = forAll(collectionPairs) { case (t, coll) => + property("counts must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => val results = for ((pred, ind) <- countPredicates.zipWithIndex) yield { val tc = t.count(pred) val cc = coll.count(pred) @@ -143,19 +143,19 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col results.reduceLeft(_ && _) } - property("forall must be equal") = forAll(collectionPairs) { case (t, coll) => + property("forall must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => val results = for ((pred, ind) <- forallPredicates.zipWithIndex) yield ("op index: " + ind) |: t.forall(pred) == coll.forall(pred) results.reduceLeft(_ && _) } - property("exists must be equal") = forAll(collectionPairs) { case (t, coll) => + property("exists must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => val results = for ((pred, ind) <- existsPredicates.zipWithIndex) yield ("op index: " + ind) |: t.exists(pred) == coll.exists(pred) results.reduceLeft(_ && _) } - property("both must find or not find an element") = forAll(collectionPairs) { case (t, coll) => + property("both must find or not find an element") = forAllNoShrink(collectionPairs) { case (t, coll) => val results = for ((pred, ind) <- findPredicates.zipWithIndex) yield { val ft = t.find(pred) val fcoll = coll.find(pred) @@ -164,7 +164,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col results.reduceLeft(_ && _) } - property("mappings must be equal") = forAll(collectionPairs) { case (t, coll) => + property("mappings must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => val results = for ((f, ind) <- mapFunctions.zipWithIndex) yield { val ms = t.map(f) val mp = coll.map(f) @@ -185,7 +185,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col results.reduceLeft(_ && _) } - property("collects must be equal") = forAll(collectionPairs) { case (t, coll) => + property("collects must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => val results = for ((f, ind) <- partialMapFunctions.zipWithIndex) yield { val ps = t.collect(f) val pp = coll.collect(f) @@ -201,12 +201,12 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col results.reduceLeft(_ && _) } - property("flatMaps must be equal") = forAll(collectionPairs) { case (t, coll) => + property("flatMaps must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for ((f, ind) <- flatMapFunctions.zipWithIndex) yield ("op index: " + ind) |: areEqual(t.flatMap(f), coll.flatMap(f))).reduceLeft(_ && _) } - property("filters must be equal") = forAll(collectionPairs) { case (t, coll) => + property("filters must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for ((p, ind) <- filterPredicates.zipWithIndex) yield { val tf = t.filter(p) val cf = coll.filter(p) @@ -235,7 +235,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col }).reduceLeft(_ && _) } - property("filterNots must be equal") = forAll(collectionPairs) { case (t, coll) => + property("filterNots must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for ((p, ind) <- filterNotPredicates.zipWithIndex) yield { val tf = t.filterNot(p) val cf = coll.filterNot(p) @@ -244,7 +244,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col }).reduceLeft(_ && _) } - if (!isCheckingViews) property("partitions must be equal") = forAll(collectionPairs) { case (t, coll) => + if (!isCheckingViews) property("partitions must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for ((p, ind) <- partitionPredicates.zipWithIndex) yield { val tpart = t.partition(p) val cpart = coll.partition(p) @@ -258,15 +258,15 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col }).reduceLeft(_ && _) } - if (hasStrictOrder) property("takes must be equal") = forAll(collectionPairsWithLengths) { case (t, coll, n) => + if (hasStrictOrder) property("takes must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (t, coll, n) => ("take " + n + " elements") |: t.take(n) == coll.take(n) } - if (hasStrictOrder) property("drops must be equal") = forAll(collectionPairsWithLengths) { case (t, coll, n) => + if (hasStrictOrder) property("drops must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (t, coll, n) => ("drop " + n + " elements") |: t.drop(n) == coll.drop(n) } - if (hasStrictOrder) property("slices must be equal") = forAll(collectionPairsWith2Indices) + if (hasStrictOrder) property("slices must be equal") = forAllNoShrink(collectionPairsWith2Indices) { case (t, coll, fr, slicelength) => val from = if (fr < 0) 0 else fr val until = if (from + slicelength > t.size) t.size else from + slicelength @@ -290,7 +290,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col ("slice from " + from + " until " + until) |: tsl == collsl } - if (hasStrictOrder) property("splits must be equal") = forAll(collectionPairsWithLengths) { case (t, coll, n) => + if (hasStrictOrder) property("splits must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (t, coll, n) => val tspl = t.splitAt(n) val cspl = coll.splitAt(n) if (tspl != cspl) { @@ -303,7 +303,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col ("splitAt " + n) |: tspl == cspl } - if (hasStrictOrder) property("takeWhiles must be equal") = forAll(collectionPairs) { case (t, coll) => + if (hasStrictOrder) property("takeWhiles must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for ((pred, ind) <- takeWhilePredicates.zipWithIndex) yield { val tt = t.takeWhile(pred) val ct = coll.takeWhile(pred) @@ -318,7 +318,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col }).reduceLeft(_ && _) } - if (hasStrictOrder) property("spans must be equal") = forAll(collectionPairs) { case (t, coll) => + if (hasStrictOrder) property("spans must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for ((pred, ind) <- spanPredicates.zipWithIndex) yield { val tsp = t.span(pred) val csp = coll.span(pred) @@ -336,13 +336,13 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col }).reduceLeft(_ && _) } - if (hasStrictOrder) property("dropWhiles must be equal") = forAll(collectionPairs) { case (t, coll) => + if (hasStrictOrder) property("dropWhiles must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for ((pred, ind) <- dropWhilePredicates.zipWithIndex) yield { ("operator " + ind) |: t.dropWhile(pred) == coll.dropWhile(pred) }).reduceLeft(_ && _) } - property("folds must be equal for assoc. operators") = forAll(collectionPairs) { case (t, coll) => + property("folds must be equal for assoc. operators") = forAllNoShrink(collectionPairs) { case (t, coll) => (for (((first, op), ind) <- foldArguments.zipWithIndex) yield { val tres = t.foldLeft(first)(op) val cres = coll.fold(first)(op) @@ -389,7 +389,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col } } - if (hasStrictOrder) property("copies to array must be equal") = forAll(collectionPairs) { case (t, coll) => + if (hasStrictOrder) property("copies to array must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => val tarr = newArray(t.size) val collarr = newArray(coll.size) t.copyToArray(tarr, 0, t.size) @@ -403,7 +403,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col tarr.toSeq == collarr.toSeq } - if (hasStrictOrder) property("scans must be equal") = forAll(collectionPairs) { + if (hasStrictOrder) property("scans must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for (((first, op), ind) <- foldArguments.zipWithIndex) yield { val tscan = t.scanLeft(first)(op) @@ -419,7 +419,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col }).reduceLeft(_ && _) } - property("groupBy must be equal") = forAll(collectionPairs) { + property("groupBy must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) => (for ((f, ind) <- groupByFunctions.zipWithIndex) yield { val tgroup = t.groupBy(f) diff --git a/test/files/scalacheck/parallel-collections/ParallelMapCheck1.scala b/test/files/scalacheck/parallel-collections/ParallelMapCheck1.scala index d4643e7f2c74..50aa4ad0c776 100644 --- a/test/files/scalacheck/parallel-collections/ParallelMapCheck1.scala +++ b/test/files/scalacheck/parallel-collections/ParallelMapCheck1.scala @@ -17,7 +17,7 @@ import scala.collection.parallel._ abstract class ParallelMapCheck[K, V](collname: String) extends ParallelIterableCheck[(K, V)](collname) { type CollType <: ParMap[K, V] - property("gets iterated keys") = forAll(collectionPairs) { + property("gets iterated keys") = forAllNoShrink(collectionPairs) { case (t, coll) => val containsT = for ((k, v) <- t) yield (coll.get(k) == Some(v)) val containsSelf = coll.map { case (k, v) => coll.get(k) == Some(v) } diff --git a/test/files/scalacheck/parallel-collections/ParallelSeqCheck.scala b/test/files/scalacheck/parallel-collections/ParallelSeqCheck.scala index 3f8a8ad4f555..48c3d3f74504 100644 --- a/test/files/scalacheck/parallel-collections/ParallelSeqCheck.scala +++ b/test/files/scalacheck/parallel-collections/ParallelSeqCheck.scala @@ -24,6 +24,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe def fromSeq(s: Seq[T]): CollType override def instances(vals: Seq[Gen[T]]): Gen[Seq[T]] = oneOf( + Gen.const(ofSize(vals, 1)), sized( sz => ofSize(vals, sz) @@ -74,7 +75,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe coll.patch(updateStart, coll, howMany) } - property("segmentLengths must be equal") = forAll(collectionPairsWithLengths) { case (s, coll, len) => + property("segmentLengths must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (s, coll, len) => (for ((pred, ind) <- segmentLengthPredicates.zipWithIndex) yield { val slen = s.segmentLength(pred, if (len < 0) 0 else len) val clen = coll.segmentLength(pred, len) @@ -88,13 +89,13 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe }).reduceLeft(_ && _) } - property("prefixLengths must be equal") = forAll(collectionPairs) { case (s, coll) => + property("prefixLengths must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) => (for ((pred, ind) <- segmentLengthPredicates.zipWithIndex) yield { ("operator " + ind) |: s.prefixLength(pred) == coll.prefixLength(pred) }).reduceLeft(_ && _) } - property("indexWheres must be equal") = forAll(collectionPairsWithLengths) { case (s, coll, len) => + property("indexWheres must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (s, coll, len) => (for ((pred, ind) <- indexWherePredicates.zipWithIndex) yield { val sind = s.indexWhere(pred, len) val cind = coll.indexWhere(pred, len) @@ -109,7 +110,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe }).reduceLeft(_ && _) } - property("lastIndexWheres must be equal") = forAll(collectionPairsWithLengths) { case (s, coll, len) => + property("lastIndexWheres must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (s, coll, len) => (for ((pred, ind) <- lastIndexWherePredicates.zipWithIndex) yield { val end = if (len >= s.size) s.size - 1 else len val sind = s.lastIndexWhere(pred, end) @@ -118,7 +119,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe }).reduceLeft(_ && _) } - property("reverses must be equal") = forAll(collectionPairs) { case (s, coll) => + property("reverses must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) => (s.length == 0 && s.getClass == classOf[collection.immutable.Range]) || { val sr = s.reverse @@ -133,13 +134,13 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe } } - property("reverseMaps must be equal") = forAll(collectionPairs) { case (s, coll) => + property("reverseMaps must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) => (for ((f, ind) <- reverseMapFunctions.zipWithIndex) yield { ("operator " + ind) |: s.reverseMap(f) == coll.reverseMap(f) }).reduceLeft(_ && _) } - property("sameElements must be equal") = forAll(collectionPairsWithModifiedWithLengths) { + property("sameElements must be equal") = forAllNoShrink(collectionPairsWithModifiedWithLengths) { case (s, coll, collmodif, len) => val pos = if (len < 0) 0 else len val scm = s.sameElements(collmodif) @@ -171,7 +172,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe }).reduceLeft(_ && _) } - property("startsWiths must be equal") = forAll(collectionPairsWithModifiedWithLengths) { + property("startsWiths must be equal") = forAllNoShrink(collectionPairsWithModifiedWithLengths) { case (s, coll, collmodif, len) => val pos = if (len < 0) 0 else len ("start with self" |: s.startsWith(s) == coll.startsWith(coll)) && @@ -195,7 +196,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe }).reduceLeft(_ && _) } - property("endsWiths must be equal") = forAll(collectionPairsWithModified) { + property("endsWiths must be equal") = forAllNoShrink(collectionPairsWithModified) { case (s, coll, collmodif) => ("ends with self" |: s.endsWith(s) == coll.endsWith(s)) && ("ends with tail" |: (s.length == 0 || s.endsWith(s.tail) == coll.endsWith(coll.tail))) && @@ -214,7 +215,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe }).reduceLeft(_ && _) } - property("unions must be equal") = forAll(collectionPairsWithModified) { case (s, coll, collmodif) => + property("unions must be equal") = forAllNoShrink(collectionPairsWithModified) { case (s, coll, collmodif) => ("modified" |: s.union(collmodif.seq) == coll.union(collmodif)) && ("empty" |: s.union(Nil) == coll.union(fromSeq(Nil))) } @@ -233,7 +234,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe ("with one" |: (s.length == 0 || s.patch(from, List(s(0)), 1) == coll.patch(from, fromSeq(List(coll(0))), 1))) } - if (!isCheckingViews) property("updates must be equal") = forAll(collectionPairsWithLengths) { case (s, coll, len) => + if (!isCheckingViews) property("updates must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (s, coll, len) => val pos = if (len >= s.length) s.length - 1 else len if (s.length > 0) { val supd = s.updated(pos, s(0)) @@ -248,15 +249,15 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe } else "trivially" |: true } - property("prepends must be equal") = forAll(collectionPairs) { case (s, coll) => + property("prepends must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) => s.length == 0 || s(0) +: s == coll(0) +: coll } - property("appends must be equal") = forAll(collectionPairs) { case (s, coll) => + property("appends must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) => s.length == 0 || s :+ s(0) == coll :+ coll(0) } - property("padTos must be equal") = forAll(collectionPairsWithLengths) { case (s, coll, len) => + property("padTos must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (s, coll, len) => val someValue = sampleValue val sdoub = s.padTo(len * 2, someValue) val cdoub = coll.padTo(len * 2, someValue) @@ -267,10 +268,10 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe println(cdoub) } ("smaller" |: s.padTo(len / 2, someValue) == coll.padTo(len / 2, someValue)) && - ("bigger" |: sdoub == cdoub) + ("bigger" |: sdoub == cdoub) } - property("corresponds must be equal") = forAll(collectionPairsWithModified) { case (s, coll, modified) => + property("corresponds must be equal") = forAllNoShrink(collectionPairsWithModified) { case (s, coll, modified) => val modifcut = modified.toSeq.slice(0, modified.length) ("self" |: s.corresponds(s)(_ == _) == coll.corresponds(coll)(_ == _)) && ("modified" |: s.corresponds(modified.seq)(_ == _) == coll.corresponds(modified)(_ == _)) && diff --git a/test/files/scalacheck/parallel-collections/ParallelSetCheck.scala b/test/files/scalacheck/parallel-collections/ParallelSetCheck.scala index 56f7832fed0e..c22dddf96d80 100644 --- a/test/files/scalacheck/parallel-collections/ParallelSetCheck.scala +++ b/test/files/scalacheck/parallel-collections/ParallelSetCheck.scala @@ -17,7 +17,7 @@ import scala.collection.parallel._ abstract class ParallelSetCheck[T](collname: String) extends ParallelIterableCheck[T](collname) { type CollType <: ParSet[T] - property("gets iterated keys") = forAll(collectionPairs) { + property("gets iterated keys") = forAllNoShrink(collectionPairs) { case (t, coll) => val containsT = for (elem <- t) yield (coll.contains(elem)) val containsSelf = for (elem <- coll) yield (coll.contains(elem)) From add83b8a8fea641c3ba96ed963c25c84ffe137fb Mon Sep 17 00:00:00 2001 From: Dima Tkach Date: Tue, 28 Jun 2016 07:26:45 -0400 Subject: [PATCH 112/153] Override `.slice` in ArrayOps to use arraycopy. This makes it ~10x faster when copying large chunks arround. My benchmark: def bm(duration: Long)(f: => Unit): Int = { val end = System.currentTimeMillis + duration var count = 0 while(System.currentTimeMillis < end) { f count += 1 } count } def measure(seconds: Int)(f: => Unit) = (1 to seconds).map { _ => bm(1000)(f) }.sum / seconds val array = scala.util.Random.alphanumeric.take(1000).toArray measure(20) { array.slice(100, 500) } // ~5 million measure(20) { scala.collection.WrappedArray(array).slice(100, 500) } // ~300K --- src/library/scala/collection/mutable/ArrayOps.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index 507585b9cf7b..b384decbfb11 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -41,6 +41,17 @@ sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomPara if (l > 0) Array.copy(repr, 0, xs, start, l) } + override def slice(from: Int, until: Int): Array[T] = { + val lo = math.max(from, 0) + val hi = math.min(math.max(until, 0), repr.length) + val size = math.max(hi-lo, 0) + val result = java.lang.reflect.Array.newInstance(elementClass, size) + if(size > 0) { + Array.copy(repr, lo, result, 0, size) + } + result.asInstanceOf[Array[T]] + } + override def toArray[U >: T : ClassTag]: Array[U] = { val thatElementClass = implicitly[ClassTag[U]].runtimeClass if (elementClass eq thatElementClass) From 367bab451415d8d4c78253e1aa60cb5301ac0a93 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 6 Jun 2016 14:24:38 +1000 Subject: [PATCH 113/153] Remove nonsensical body for trait getter This corrects an error in the change to the trait encoding in #5003: getters in traits should have empty bodies and be emitted as abstract. ``` % ~/scala/2.12.0-M4/bin/scalac sandbox/test.scala && javap -c T Compiled from "test.scala" public interface T { public abstract void T$_setter_$x_$eq(int); public int x(); Code: 0: aload_0 1: invokeinterface #15, 1 // InterfaceMethod x:()I 6: ireturn public int y(); Code: 0: aload_0 1: invokeinterface #20, 1 // InterfaceMethod y:()I 6: ireturn public void y_$eq(int); Code: 0: aload_0 1: iload_1 2: invokeinterface #24, 2 // InterfaceMethod y_$eq:(I)V 7: return public void $init$(); Code: 0: aload_0 1: bipush 42 3: invokeinterface #29, 2 // InterfaceMethod T$_setter_$x_$eq:(I)V 8: aload_0 9: bipush 24 11: invokeinterface #24, 2 // InterfaceMethod y_$eq:(I)V 16: return } % qscalac sandbox/test.scala && javap -c T Compiled from "test.scala" public interface T { public abstract void T$_setter_$x_$eq(int); public abstract int x(); public abstract int y(); public abstract void y_$eq(int); public static void $init$(T); Code: 0: aload_0 1: bipush 42 3: invokeinterface #21, 2 // InterfaceMethod T$_setter_$x_$eq:(I)V 8: aload_0 9: bipush 24 11: invokeinterface #23, 2 // InterfaceMethod y_$eq:(I)V 16: return public void $init$(); Code: 0: aload_0 1: invokestatic #27 // Method $init$:(LT;)V 4: return } ``` --- src/compiler/scala/tools/nsc/transform/Mixin.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 19ba9345faea..6df0b992ed49 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -1001,8 +1001,13 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val parents1 = currentOwner.info.parents map (t => TypeTree(t) setPos tree.pos) // mark fields which can be nulled afterward lazyValNullables = nullableFields(templ) withDefaultValue Set() + val bodyEmptyAccessors = if (!sym.enclClass.isTrait) body else body mapConserve { + case dd: DefDef if dd.symbol.isAccessor && !dd.symbol.isLazy => + deriveDefDef(dd)(_ => EmptyTree) + case tree => tree + } // add all new definitions to current class or interface - treeCopy.Template(tree, parents1, self, addNewDefs(currentOwner, body)) + treeCopy.Template(tree, parents1, self, addNewDefs(currentOwner, bodyEmptyAccessors)) case Select(qual, name) if sym.owner.isTrait && !sym.isMethod => // refer to fields in some trait an abstract getter in the interface. From 9f54af3270396724928b335ba8d14282973898fd Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 6 Jun 2016 14:24:38 +1000 Subject: [PATCH 114/153] Better diagnostic for optimizer crashes --- .../nsc/backend/jvm/analysis/BackendUtils.scala | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index 9abd1d80067d..513c71fe2eeb 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -6,11 +6,12 @@ import scala.annotation.switch import scala.tools.asm.{Handle, Type} import scala.tools.asm.Opcodes._ import scala.tools.asm.tree._ -import scala.tools.asm.tree.analysis.{Frame, BasicInterpreter, Analyzer, Value} +import scala.tools.asm.tree.analysis._ import GenBCode._ import scala.tools.nsc.backend.jvm.BTypes._ import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._ import java.lang.invoke.LambdaMetafactory + import scala.collection.mutable import scala.collection.JavaConverters._ @@ -32,8 +33,13 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { */ class AsmAnalyzer[V <: Value](methodNode: MethodNode, classInternalName: InternalName, val analyzer: Analyzer[V] = new Analyzer(new BasicInterpreter)) { computeMaxLocalsMaxStack(methodNode) - analyzer.analyze(classInternalName, methodNode) - def frameAt(instruction: AbstractInsnNode): Frame[V] = analyzer.frameAt(instruction, methodNode) + try { + analyzer.analyze(classInternalName, methodNode) + } catch { + case ae: AnalyzerException => + throw new AnalyzerException(null, "While processing " + classInternalName + "." + methodNode.name, ae) + } + def frameAt(instruction: AbstractInsnNode): Frame[V] = analyzer.frameAt(instruction, methodNode) } /** From a9bebf80aae7ab2e30d84c7cd02abef2349d59d5 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 6 Jun 2016 14:24:38 +1000 Subject: [PATCH 115/153] Remove stray .class file from version control --- test/files/run/t8601e/StaticInit.class | Bin 417 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/files/run/t8601e/StaticInit.class diff --git a/test/files/run/t8601e/StaticInit.class b/test/files/run/t8601e/StaticInit.class deleted file mode 100644 index 99a0e2a643d76e1528a256cbcaad359d2bfbc85d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 417 zcmY*VO-sW-5Pj36O`4`nY_)2&f;a8Kg6E$KgFLRf&~S= z`=i83C>HlHJM;FvH#7VF^Zp57A6pho)J!Z}SV7&uss$ajA`GkE6(P@NJY}6S(&&Ej$SBf_@$h zMX3Hko|?#bKrrNecQjT{*&a98=6)uB2C*Sqa+c$qC*fG;s>wGGg?wuUddY|tj)e^5 zW#Rl$4_TU?dNub3?HQ#H=+`skzueX<3aK`SR9k_@QDdzRm)pBpMJ`(|Wu)pa(sfEe From d3c0885a1a88e9d52902a527650319010d7ced67 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 6 Jun 2016 14:24:38 +1000 Subject: [PATCH 116/153] Don't minimize parents of java defined syms. --- .../scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index d83b4a1d856e..21ea351a998f 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -234,12 +234,13 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { val allParents = classParents ++ classSym.annotations.flatMap(newParentForAnnotation) + val minimizedParents = if (classSym.isJavaDefined) allParents else erasure.minimizeParents(allParents) // We keep the superClass when computing minimizeParents to eliminate more interfaces. // Example: T can be eliminated from D // trait T // class C extends T // class D extends C with T - val interfaces = erasure.minimizeParents(allParents) match { + val interfaces = minimizedParents match { case superClass :: ifs if !isInterfaceOrTrait(superClass.typeSymbol) => ifs case ifs => From 91b066aac5edf53ca18603f8486eb255514b3118 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 6 Jun 2016 14:24:38 +1000 Subject: [PATCH 117/153] Revert pruning of redundant Java parents This partially reverts the fix for SI-5278 made in 7a99c03da. The original motivation for this case to avoid bytecode that stretched platform limitations in Android. For super calls to Scala defined trait methods, we won't use `invokespecial`, but rather use `invokestatic` to a static trait implementation method. As such, we can continue to prune redundant Scala interfaces. It might be worth considering removing the pruning of redundant parents altoghether, though: - We no longer include `ScalaObject` as a parent of every class, which was mentioned as a problem in SI-5728. - Scala 2.12 has left Android behind for the time being due to use of Java 8 facilities. - javac doesn't do this, so why should we? --- .../scala/tools/nsc/transform/Erasure.scala | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 5e903946c1c4..db8e203c1cdf 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -189,18 +189,23 @@ abstract class Erasure extends AddInterfaces /* Drop redundant types (ones which are implemented by some other parent) from the immediate parents. * This is important on Android because there is otherwise an interface explosion. + * This is now restricted to Scala defined ancestors: a Java defined ancestor may need to be listed + * as an immediate parent to support an `invokespecial`. */ def minimizeParents(parents: List[Type]): List[Type] = if (parents.isEmpty) parents else { - def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait + def isRedundantParent(sym: Symbol) = sym.isInterface || sym.isTrait var rest = parents.tail var leaves = collection.mutable.ListBuffer.empty[Type] += parents.head while(rest.nonEmpty) { val candidate = rest.head - val nonLeaf = leaves exists { t => t.typeSymbol isSubClass candidate.typeSymbol } - if(!nonLeaf) { - leaves = leaves filterNot { t => isInterfaceOrTrait(t.typeSymbol) && (candidate.typeSymbol isSubClass t.typeSymbol) } - leaves += candidate + if (candidate.typeSymbol.isJavaDefined && candidate.typeSymbol.isInterface) leaves += candidate + else { + val nonLeaf = leaves exists { t => t.typeSymbol isSubClass candidate.typeSymbol } + if (!nonLeaf) { + leaves = leaves filterNot { t => isRedundantParent(t.typeSymbol) && (candidate.typeSymbol isSubClass t.typeSymbol) } + leaves += candidate + } } rest = rest.tail } From 7d51b3fd1569917cb804363bd418466a306f5c89 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 6 Jun 2016 14:24:38 +1000 Subject: [PATCH 118/153] Emit trait method bodies in statics And use this as the target of the default methods or statically resolved super or $init calls. The call-site change is predicated on `-Yuse-trait-statics` as a stepping stone for experimentation / bootstrapping. I have performed this transformation in the backend, rather than trying to reflect this in the view from Scala symbols + ASTs. We also need to add an restriction related to invokespecial to Java parents: to support a super call to one of these to implement a super accessor, the interface must be listed as a direct parent of the class. The static method names has a trailing $ added to avoid duplicate name and signature errors in classfiles. --- .../scala/tools/nsc/ast/TreeGen.scala | 3 +- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 49 +++++++----- .../tools/nsc/backend/jvm/BCodeHelpers.scala | 71 +++------------- .../nsc/backend/jvm/BCodeIdiomatic.scala | 22 +++-- .../nsc/backend/jvm/BCodeSkelBuilder.scala | 17 +++- .../scala/tools/nsc/backend/jvm/BTypes.scala | 22 +---- .../nsc/backend/jvm/BTypesFromSymbols.scala | 80 ++++++++++++++++++- .../backend/jvm/analysis/BackendUtils.scala | 14 ++-- .../nsc/backend/jvm/opt/BytecodeUtils.scala | 9 +++ .../tools/nsc/backend/jvm/opt/CallGraph.scala | 7 +- .../backend/jvm/opt/InlineInfoAttribute.scala | 13 --- .../tools/nsc/backend/jvm/opt/Inliner.scala | 28 ++++--- .../backend/jvm/opt/InlinerHeuristics.scala | 28 ++++++- .../tools/nsc/transform/Delambdafy.scala | 6 +- .../scala/tools/nsc/transform/Mixin.scala | 28 ++++++- .../instrumented/InstrumentationTest.check | 2 +- test/files/neg/trait-defaults-super.check | 4 + test/files/neg/trait-defaults-super.scala | 21 +++++ test/files/pos/trait-defaults-super.scala | 21 +++++ test/files/run/t4891.check | 3 +- test/files/run/t5652.check | 3 +- test/files/run/t7700.check | 5 +- test/files/run/t7700.scala | 16 ++-- test/files/run/t7932.check | 4 + test/files/run/t7932.scala | 10 ++- test/files/run/trait-static-clash.scala | 10 +++ .../scala/lang/traits/BytecodeTest.scala | 9 ++- .../nsc/backend/jvm/DefaultMethodTest.scala | 5 +- .../nsc/backend/jvm/DirectCompileTest.scala | 4 +- .../opt/InlinerSeparateCompilationTest.scala | 4 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 35 +++++--- .../backend/jvm/opt/ScalaInlineInfoTest.scala | 23 +++++- .../scala/tools/testing/BytecodeTesting.scala | 15 +++- 33 files changed, 385 insertions(+), 206 deletions(-) create mode 100644 test/files/neg/trait-defaults-super.check create mode 100644 test/files/neg/trait-defaults-super.scala create mode 100644 test/files/pos/trait-defaults-super.scala create mode 100644 test/files/run/trait-static-clash.scala diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 14ee7d7a7897..bc89609a596c 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -336,12 +336,13 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { * - are associating the RHS with a cloned symbol, but intend for the original * method to remain and for recursive calls to target it. */ - final def mkStatic(orig: DefDef, maybeClone: Symbol => Symbol): DefDef = { + final def mkStatic(orig: DefDef, newName: Name, maybeClone: Symbol => Symbol): DefDef = { assert(phase.erasedTypes, phase) assert(!orig.symbol.hasFlag(SYNCHRONIZED), orig.symbol.defString) val origSym = orig.symbol val origParams = orig.symbol.info.params val newSym = maybeClone(orig.symbol) + newSym.setName(newName) newSym.setFlag(STATIC) // Add an explicit self parameter val selfParamSym = newSym.newSyntheticValueParam(newSym.owner.typeConstructor, nme.SELF).setFlag(ARTIFACT) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index d7106ae908ff..55fe47bde61f 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -11,10 +11,10 @@ package jvm import scala.annotation.switch import scala.reflect.internal.Flags - import scala.tools.asm import GenBCode._ import BackendReporting._ +import scala.tools.asm.Opcodes import scala.tools.asm.tree.MethodInsnNode import scala.tools.nsc.backend.jvm.BCodeHelpers.{InvokeStyle, TestOp} @@ -637,7 +637,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { val nativeKind = tpeTK(expr) genLoad(expr, nativeKind) val MethodNameAndType(mname, methodType) = srBoxesRuntimeBoxToMethods(nativeKind) - bc.invokestatic(srBoxesRunTimeRef.internalName, mname, methodType.descriptor, app.pos) + bc.invokestatic(srBoxesRunTimeRef.internalName, mname, methodType.descriptor, itf = false, app.pos) generatedType = boxResultType(fun.symbol) case Apply(fun, List(expr)) if currentRun.runDefinitions.isUnbox(fun.symbol) => @@ -645,7 +645,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { val boxType = unboxResultType(fun.symbol) generatedType = boxType val MethodNameAndType(mname, methodType) = srBoxesRuntimeUnboxToMethods(boxType) - bc.invokestatic(srBoxesRunTimeRef.internalName, mname, methodType.descriptor, app.pos) + bc.invokestatic(srBoxesRunTimeRef.internalName, mname, methodType.descriptor, itf = false, app.pos) case app @ Apply(fun, args) => val sym = fun.symbol @@ -1058,31 +1058,40 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { } receiverClass.info // ensure types the type is up to date; erasure may add lateINTERFACE to traits - val receiverName = internalName(receiverClass) - - // super calls are only allowed to direct parents - if (style.isSuper && receiverClass.isTraitOrInterface && !cnode.interfaces.contains(receiverName)) { - thisBType.info.get.inlineInfo.lateInterfaces += receiverName - cnode.interfaces.add(receiverName) - } + val receiverBType = classBTypeFromSymbol(receiverClass) + val receiverName = receiverBType.internalName def needsInterfaceCall(sym: Symbol) = { sym.isTraitOrInterface || sym.isJavaDefined && sym.isNonBottomSubClass(definitions.ClassfileAnnotationClass) } - val jname = method.javaSimpleName.toString - val bmType = methodBTypeFromSymbol(method) - val mdescr = bmType.descriptor + val jname = method.javaSimpleName.toString + val bmType = methodBTypeFromSymbol(method) + val mdescr = bmType.descriptor + val isInterface = receiverBType.isInterface.get import InvokeStyle._ - style match { - case Static => bc.invokestatic (receiverName, jname, mdescr, pos) - case Special => bc.invokespecial (receiverName, jname, mdescr, pos) - case Virtual => - if (needsInterfaceCall(receiverClass)) bc.invokeinterface(receiverName, jname, mdescr, pos) - else bc.invokevirtual (receiverName, jname, mdescr, pos) - case Super => bc.invokespecial (receiverName, jname, mdescr, pos) + if (style == Super) { + assert(receiverClass == methodOwner, s"for super call, expecting $receiverClass == $methodOwner") + if (receiverClass.isTrait && !receiverClass.isJavaDefined) { + val staticDesc = MethodBType(typeToBType(method.owner.info) :: bmType.argumentTypes, bmType.returnType).descriptor + val staticName = traitImplMethodName(method).toString + bc.invokestatic(receiverName, staticName, staticDesc, isInterface, pos) + } else { + if (receiverClass.isTraitOrInterface) { + // An earlier check in Mixin reports an error in this case, so it doesn't reach the backend + assert(cnode.interfaces.contains(receiverName), s"cannot invokespecial $receiverName.$jname, the interface is not a direct parent.") + } + bc.invokespecial(receiverName, jname, mdescr, isInterface, pos) + } + } else { + val opc = style match { + case Static => Opcodes.INVOKESTATIC + case Special => Opcodes.INVOKESPECIAL + case Virtual => if (isInterface) Opcodes.INVOKEINTERFACE else Opcodes.INVOKEVIRTUAL + } + bc.emitInvoke(opc, receiverName, jname, mdescr, isInterface, pos) } bmType.returnType diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index 5a5747c81f65..df3c2cb3d5ef 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -11,6 +11,7 @@ import scala.tools.asm import scala.tools.nsc.io.AbstractFile import GenBCode._ import BackendReporting._ +import scala.reflect.internal.Flags /* * Traits encapsulating functionality to convert Scala AST Trees into ASM ClassNodes. @@ -49,6 +50,14 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { } } + def needsStaticImplMethod(sym: Symbol) = sym.hasAttachment[global.mixer.NeedStaticImpl.type] + + final def traitImplMethodName(sym: Symbol): Name = { + val name = sym.javaSimpleName + if (sym.isMixinConstructor) name + else name.append(nme.NAME_JOIN_STRING) + } + /** * True if `classSym` is an anonymous class or a local class. I.e., false if `classSym` is a * member class. This method is used to decide if we should emit an EnclosingMethod attribute. @@ -230,58 +239,6 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { sym.isErroneous } - /** - * Build the [[InlineInfo]] for a class symbol. - */ - def buildInlineInfoFromClassSymbol(classSym: Symbol, classSymToInternalName: Symbol => InternalName, methodSymToDescriptor: Symbol => String): InlineInfo = { - val isEffectivelyFinal = classSym.isEffectivelyFinal - - val sam = { - if (classSym.isEffectivelyFinal) None - else { - // Phase travel necessary. For example, nullary methods (getter of an abstract val) get an - // empty parameter list in later phases and would therefore be picked as SAM. - val samSym = exitingPickler(definitions.samOf(classSym.tpe)) - if (samSym == NoSymbol) None - else Some(samSym.javaSimpleName.toString + methodSymToDescriptor(samSym)) - } - } - - var warning = Option.empty[ClassSymbolInfoFailureSI9111] - - // Primitive methods cannot be inlined, so there's no point in building a MethodInlineInfo. Also, some - // primitive methods (e.g., `isInstanceOf`) have non-erased types, which confuses [[typeToBType]]. - val methodInlineInfos = classSym.info.decls.iterator.filter(m => m.isMethod && !scalaPrimitives.isPrimitive(m)).flatMap({ - case methodSym => - if (completeSilentlyAndCheckErroneous(methodSym)) { - // Happens due to SI-9111. Just don't provide any MethodInlineInfo for that method, we don't need fail the compiler. - if (!classSym.isJavaDefined) devWarning("SI-9111 should only be possible for Java classes") - warning = Some(ClassSymbolInfoFailureSI9111(classSym.fullName)) - None - } else { - val name = methodSym.javaSimpleName.toString // same as in genDefDef - val signature = name + methodSymToDescriptor(methodSym) - - // In `trait T { object O }`, `oSym.isEffectivelyFinalOrNotOverridden` is true, but the - // method is abstract in bytecode, `defDef.rhs.isEmpty`. Abstract methods are excluded - // so they are not marked final in the InlineInfo attribute. - // - // However, due to https://github.com/scala/scala-dev/issues/126, this currently does not - // work, the abstract accessor for O will be marked effectivelyFinal. - val effectivelyFinal = methodSym.isEffectivelyFinalOrNotOverridden && !methodSym.isDeferred - - val info = MethodInlineInfo( - effectivelyFinal = effectivelyFinal, - annotatedInline = methodSym.hasAnnotation(ScalaInlineClass), - annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass) - ) - Some((signature, info)) - } - }).toMap - - InlineInfo(isEffectivelyFinal, sam, methodInlineInfos, warning) - } - /* * must-single-thread */ @@ -568,15 +525,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { /** * The class internal name for a given class symbol. */ - final def internalName(sym: Symbol): String = { - // For each java class, the scala compiler creates a class and a module (thus a module class). - // If the `sym` is a java module class, we use the java class instead. This ensures that the - // ClassBType is created from the main class (instead of the module class). - // The two symbols have the same name, so the resulting internalName is the same. - // Phase travel (exitingPickler) required for SI-6613 - linkedCoC is only reliable in early phases (nesting) - val classSym = if (sym.isJavaDefined && sym.isModuleClass) exitingPickler(sym.linkedClassOfClass) else sym - classBTypeFromSymbol(classSym).internalName - } + final def internalName(sym: Symbol): String = classBTypeFromSymbol(sym).internalName } // end of trait BCInnerClassGen trait BCAnnotGen extends BCInnerClassGen { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala index ed1b4ec3255e..e3d45a9b3e90 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala @@ -190,6 +190,7 @@ abstract class BCodeIdiomatic extends SubComponent { JavaStringBuilderClassName, INSTANCE_CONSTRUCTOR_NAME, "()V", + itf = false, pos ) } @@ -373,30 +374,27 @@ abstract class BCodeIdiomatic extends SubComponent { final def rem(tk: BType) { emitPrimitive(JCodeMethodN.remOpcodes, tk) } // can-multi-thread // can-multi-thread - final def invokespecial(owner: String, name: String, desc: String, pos: Position) { - addInvoke(Opcodes.INVOKESPECIAL, owner, name, desc, false, pos) + final def invokespecial(owner: String, name: String, desc: String, itf: Boolean, pos: Position): Unit = { + emitInvoke(Opcodes.INVOKESPECIAL, owner, name, desc, itf, pos) } // can-multi-thread - final def invokestatic(owner: String, name: String, desc: String, pos: Position) { - addInvoke(Opcodes.INVOKESTATIC, owner, name, desc, false, pos) + final def invokestatic(owner: String, name: String, desc: String, itf: Boolean, pos: Position): Unit = { + emitInvoke(Opcodes.INVOKESTATIC, owner, name, desc, itf, pos) } // can-multi-thread - final def invokeinterface(owner: String, name: String, desc: String, pos: Position) { - addInvoke(Opcodes.INVOKEINTERFACE, owner, name, desc, true, pos) + final def invokeinterface(owner: String, name: String, desc: String, pos: Position): Unit = { + emitInvoke(Opcodes.INVOKEINTERFACE, owner, name, desc, itf = true, pos) } // can-multi-thread - final def invokevirtual(owner: String, name: String, desc: String, pos: Position) { - addInvoke(Opcodes.INVOKEVIRTUAL, owner, name, desc, false, pos) + final def invokevirtual(owner: String, name: String, desc: String, pos: Position): Unit = { + emitInvoke(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf = false, pos) } - private def addInvoke(opcode: Int, owner: String, name: String, desc: String, itf: Boolean, pos: Position) = { + def emitInvoke(opcode: Int, owner: String, name: String, desc: String, itf: Boolean, pos: Position): Unit = { val node = new MethodInsnNode(opcode, owner, name, desc, itf) jmethod.instructions.add(node) if (settings.optInlinerEnabled) callsitePositions(node) = pos } - final def invokedynamic(owner: String, name: String, desc: String) { - jmethod.visitMethodInsn(Opcodes.INVOKEDYNAMIC, owner, name, desc) - } // can-multi-thread final def goTo(label: asm.Label) { jmethod.visitJumpInsn(Opcodes.GOTO, label) } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala index bddc41e5c6ac..1bff8519eca3 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala @@ -488,7 +488,22 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { case ValDef(mods, name, tpt, rhs) => () // fields are added in `genPlainClass()`, via `addClassFields()` - case dd : DefDef => genDefDef(dd) + case dd : DefDef => + val sym = dd.symbol + if (needsStaticImplMethod(sym)) { + val staticDefDef = global.gen.mkStatic(dd, traitImplMethodName(sym), _.cloneSymbol) + val forwarderDefDef = { + val forwarderBody = Apply(global.gen.mkAttributedRef(staticDefDef.symbol), This(sym.owner).setType(sym.owner.typeConstructor) :: dd.vparamss.head.map(p => global.gen.mkAttributedIdent(p.symbol))).setType(sym.info.resultType) + // we don't want to the optimizer to inline the static method into the forwarder. Instead, + // the backend has a special case to transitively inline into a callsite of the forwarder + // when the forwarder itself is inlined. + forwarderBody.updateAttachment(NoInlineCallsiteAttachment) + deriveDefDef(dd)(_ => global.atPos(dd.pos)(forwarderBody)) + } + genDefDef(staticDefDef) + if (!sym.isMixinConstructor) + genDefDef(forwarderDefDef) + } else genDefDef(dd) case Template(_, _, body) => body foreach gen diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index a708feb0a7b8..7b2686e7a9be 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -225,8 +225,7 @@ abstract class BTypes { val inlineInfo = inlineInfoFromClassfile(classNode) - val classfileInterfaces: List[ClassBType] = classNode.interfaces.asScala.map(classBTypeFromParsedClassfile)(collection.breakOut) - val interfaces = classfileInterfaces.filterNot(i => inlineInfo.lateInterfaces.contains(i.internalName)) + val interfaces: List[ClassBType] = classNode.interfaces.asScala.map(classBTypeFromParsedClassfile)(collection.breakOut) classBType.info = Right(ClassInfo(superClass, interfaces, flags, nestedClasses, nestedInfo, inlineInfo)) classBType @@ -1147,25 +1146,6 @@ object BTypes { sam: Option[String], methodInfos: Map[String, MethodInlineInfo], warning: Option[ClassInlineInfoWarning]) { - /** - * A super call (invokespecial) to a default method T.m is only allowed if the interface T is - * a direct parent of the class. Super calls are introduced for example in Mixin when generating - * forwarder methods: - * - * trait T { override def clone(): Object = "hi" } - * trait U extends T - * class C extends U - * - * The class C gets a forwarder that invokes T.clone(). During code generation the interface T - * is added as direct parent to class C. Note that T is not a (direct) parent in the frontend - * type of class C. - * - * All interfaces that are added to a class during code generation are added to this buffer and - * stored in the InlineInfo classfile attribute. This ensures that the ClassBTypes for a - * specific class is the same no matter if it's constructed from a Symbol or from a classfile. - * This is tested in BTypesFromClassfileTest. - */ - val lateInterfaces: ListBuffer[InternalName] = ListBuffer.empty } val EmptyInlineInfo = InlineInfo(false, None, Map.empty, None) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 21ea351a998f..1a4590e7d175 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -97,11 +97,19 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { * for the Nothing / Null. If used for example as a parameter type, we use the runtime classes * in the classfile method signature. */ - final def classBTypeFromSymbol(classSym: Symbol): ClassBType = { + final def classBTypeFromSymbol(sym: Symbol): ClassBType = { + // For each java class, the scala compiler creates a class and a module (thus a module class). + // If the `sym` is a java module class, we use the java class instead. This ensures that the + // ClassBType is created from the main class (instead of the module class). + // The two symbols have the same name, so the resulting internalName is the same. + // Phase travel (exitingPickler) required for SI-6613 - linkedCoC is only reliable in early phases (nesting) + val classSym = if (sym.isJavaDefined && sym.isModuleClass) exitingPickler(sym.linkedClassOfClass) else sym + assert(classSym != NoSymbol, "Cannot create ClassBType from NoSymbol") assert(classSym.isClass, s"Cannot create ClassBType from non-class symbol $classSym") assertClassNotArrayNotPrimitive(classSym) assert(!primitiveTypeToBType.contains(classSym) || isCompilingPrimitive, s"Cannot create ClassBType for primitive class symbol $classSym") + if (classSym == NothingClass) srNothingRef else if (classSym == NullClass) srNullRef else { @@ -509,7 +517,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { * classfile attribute. */ private def buildInlineInfo(classSym: Symbol, internalName: InternalName): InlineInfo = { - def buildFromSymbol = buildInlineInfoFromClassSymbol(classSym, classBTypeFromSymbol(_).internalName, methodBTypeFromSymbol(_).descriptor) + def buildFromSymbol = buildInlineInfoFromClassSymbol(classSym) // phase travel required, see implementation of `compiles`. for nested classes, it checks if the // enclosingTopLevelClass is being compiled. after flatten, all classes are considered top-level, @@ -530,6 +538,74 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { } } + /** + * Build the [[InlineInfo]] for a class symbol. + */ + def buildInlineInfoFromClassSymbol(classSym: Symbol): InlineInfo = { + val isEffectivelyFinal = classSym.isEffectivelyFinal + + val sam = { + if (classSym.isEffectivelyFinal) None + else { + // Phase travel necessary. For example, nullary methods (getter of an abstract val) get an + // empty parameter list in later phases and would therefore be picked as SAM. + val samSym = exitingPickler(definitions.samOf(classSym.tpe)) + if (samSym == NoSymbol) None + else Some(samSym.javaSimpleName.toString + methodBTypeFromSymbol(samSym).descriptor) + } + } + + var warning = Option.empty[ClassSymbolInfoFailureSI9111] + + // Primitive methods cannot be inlined, so there's no point in building a MethodInlineInfo. Also, some + // primitive methods (e.g., `isInstanceOf`) have non-erased types, which confuses [[typeToBType]]. + val methodInlineInfos = classSym.info.decls.iterator.filter(m => m.isMethod && !scalaPrimitives.isPrimitive(m)).flatMap({ + case methodSym => + if (completeSilentlyAndCheckErroneous(methodSym)) { + // Happens due to SI-9111. Just don't provide any MethodInlineInfo for that method, we don't need fail the compiler. + if (!classSym.isJavaDefined) devWarning("SI-9111 should only be possible for Java classes") + warning = Some(ClassSymbolInfoFailureSI9111(classSym.fullName)) + Nil + } else { + val name = methodSym.javaSimpleName.toString // same as in genDefDef + val signature = name + methodBTypeFromSymbol(methodSym).descriptor + + // In `trait T { object O }`, `oSym.isEffectivelyFinalOrNotOverridden` is true, but the + // method is abstract in bytecode, `defDef.rhs.isEmpty`. Abstract methods are excluded + // so they are not marked final in the InlineInfo attribute. + // + // However, due to https://github.com/scala/scala-dev/issues/126, this currently does not + // work, the abstract accessor for O will be marked effectivelyFinal. + val effectivelyFinal = methodSym.isEffectivelyFinalOrNotOverridden && !methodSym.isDeferred + + val info = MethodInlineInfo( + effectivelyFinal = effectivelyFinal, + annotatedInline = methodSym.hasAnnotation(ScalaInlineClass), + annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass)) + + if (needsStaticImplMethod(methodSym)) { + val staticName = traitImplMethodName(methodSym).toString + val selfParam = methodSym.newSyntheticValueParam(methodSym.owner.typeConstructor, nme.SELF) + val staticMethodType = methodSym.info match { + case mt @ MethodType(params, res) => copyMethodType(mt, selfParam :: params, res) + } + val staticMethodSignature = staticName + methodBTypeFromMethodType(staticMethodType, isConstructor = false) + val staticMethodInfo = MethodInlineInfo( + effectivelyFinal = true, + annotatedInline = info.annotatedInline, + annotatedNoInline = info.annotatedNoInline) + if (methodSym.isMixinConstructor) + List((staticMethodSignature, staticMethodInfo)) + else + List((signature, info), (staticMethodSignature, staticMethodInfo)) + } else + List((signature, info)) + } + }).toMap + + InlineInfo(isEffectivelyFinal, sam, methodInlineInfos, warning) + } + /** * For top-level objects without a companion class, the compiler generates a mirror class with * static forwarders (Java compat). There's no symbol for the mirror class, but we still need a diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index 513c71fe2eeb..539435a32604 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -2,18 +2,18 @@ package scala.tools.nsc package backend.jvm package analysis +import java.lang.invoke.LambdaMetafactory + import scala.annotation.switch -import scala.tools.asm.{Handle, Type} +import scala.collection.JavaConverters._ +import scala.collection.mutable import scala.tools.asm.Opcodes._ import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ -import GenBCode._ +import scala.tools.asm.{Handle, Type} import scala.tools.nsc.backend.jvm.BTypes._ +import scala.tools.nsc.backend.jvm.GenBCode._ import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._ -import java.lang.invoke.LambdaMetafactory - -import scala.collection.mutable -import scala.collection.JavaConverters._ /** * This component hosts tools and utilities used in the backend that require access to a `BTypes` @@ -39,7 +39,7 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { case ae: AnalyzerException => throw new AnalyzerException(null, "While processing " + classInternalName + "." + methodNode.name, ae) } - def frameAt(instruction: AbstractInsnNode): Frame[V] = analyzer.frameAt(instruction, methodNode) + def frameAt(instruction: AbstractInsnNode): Frame[V] = analyzer.frameAt(instruction, methodNode) } /** diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala index 63906d80e50b..e21c46dbe99e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala @@ -93,6 +93,15 @@ object BytecodeUtils { op == INVOKESPECIAL || op == INVOKESTATIC } + def isVirtualCall(instruction: AbstractInsnNode): Boolean = { + val op = instruction.getOpcode + op == INVOKEVIRTUAL || op == INVOKEINTERFACE + } + + def isCall(instruction: AbstractInsnNode): Boolean = { + isNonVirtualCall(instruction) || isVirtualCall(instruction) + } + def isExecutable(instruction: AbstractInsnNode): Boolean = instruction.getOpcode >= 0 def isConstructor(methodNode: MethodNode): Boolean = { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index 40344809bff6..d6942d9ff99b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -9,11 +9,11 @@ package opt import scala.collection.immutable.IntMap import scala.reflect.internal.util.{NoPosition, Position} -import scala.tools.asm.{Opcodes, Type, Handle} +import scala.tools.asm.{Handle, Opcodes, Type} import scala.tools.asm.tree._ import scala.collection.{concurrent, mutable} import scala.collection.JavaConverters._ -import scala.tools.nsc.backend.jvm.BTypes.InternalName +import scala.tools.nsc.backend.jvm.BTypes.{InternalName, MethodInlineInfo} import scala.tools.nsc.backend.jvm.BackendReporting._ import scala.tools.nsc.backend.jvm.analysis._ import BytecodeUtils._ @@ -67,6 +67,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { } def containsCallsite(callsite: Callsite): Boolean = callsites(callsite.callsiteMethod) contains callsite.callsiteInstruction + def findCallSite(method: MethodNode, call: MethodInsnNode): Option[Callsite] = callsites.getOrElse(method, Map.empty).get(call) def removeClosureInstantiation(indy: InvokeDynamicInsnNode, methodNode: MethodNode): Option[ClosureInstantiation] = { val methodClosureInits = closureInstantiations(methodNode) @@ -356,7 +357,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { "Invocation of" + s" ${callee.map(_.calleeDeclarationClass.internalName).getOrElse("?")}.${callsiteInstruction.name + callsiteInstruction.desc}" + s"@${callsiteMethod.instructions.indexOf(callsiteInstruction)}" + - s" in ${callsiteClass.internalName}.${callsiteMethod.name}" + s" in ${callsiteClass.internalName}.${callsiteMethod.name}${callsiteMethod.desc}" } final case class ClonedCallsite(callsite: Callsite, clonedWhenInlining: Callsite) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala index 79d26b0b4eee..5ce7072c60c0 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlineInfoAttribute.scala @@ -51,7 +51,6 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI if (inlineInfo.isEffectivelyFinal) flags |= 1 // flags |= 2 // no longer written if (inlineInfo.sam.isDefined) flags |= 4 - if (inlineInfo.lateInterfaces.nonEmpty) flags |= 8 result.putByte(flags) for (samNameDesc <- inlineInfo.sam) { @@ -79,9 +78,6 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI result.putByte(inlineInfo) } - result.putShort(inlineInfo.lateInterfaces.length) - for (i <- inlineInfo.lateInterfaces) result.putShort(cw.newUTF8(i)) - result } @@ -105,7 +101,6 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI val isFinal = (flags & 1) != 0 val hasSelf = (flags & 2) != 0 val hasSam = (flags & 4) != 0 - val hasLateInterfaces = (flags & 8) != 0 if (hasSelf) nextUTF8() // no longer used @@ -128,13 +123,7 @@ case class InlineInfoAttribute(inlineInfo: InlineInfo) extends Attribute(InlineI (name + desc, MethodInlineInfo(isFinal, isInline, isNoInline)) }).toMap - val lateInterfaces = if (!hasLateInterfaces) Nil else { - val numLateInterfaces = nextShort() - (0 until numLateInterfaces).map(_ => nextUTF8()) - } - val info = InlineInfo(isFinal, sam, infos, None) - info.lateInterfaces ++= lateInterfaces InlineInfoAttribute(info) } else { val msg = UnknownScalaInlineInfoVersion(cr.getClassName, version) @@ -161,8 +150,6 @@ object InlineInfoAttribute { * [u2] name (reference) * [u2] descriptor (reference) * [u1] isFinal (<< 0), traitMethodWithStaticImplementation (<< 1), hasInlineAnnotation (<< 2), hasNoInlineAnnotation (<< 3) - * [u2]? numLateInterfaces - * [u2] lateInterface (reference) */ final val VERSION: Byte = 1 diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index 7b4cfe2a18d2..9c5a1a9f980b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -106,6 +106,8 @@ class Inliner[BT <: BTypes](val btypes: BT) { val elided = mutable.Set.empty[InlineRequest] def nonElidedRequests(methodNode: MethodNode): Set[InlineRequest] = requestsByMethod(methodNode) diff elided + def allCallees(r: InlineRequest): Set[MethodNode] = r.post.flatMap(allCallees).toSet + r.callsite.callee.get.callee + /** * Break cycles in the inline request graph by removing callsites. * @@ -114,20 +116,20 @@ class Inliner[BT <: BTypes](val btypes: BT) { */ def breakInlineCycles: List[InlineRequest] = { // is there a path of inline requests from start to goal? - def isReachable(start: MethodNode, goal: MethodNode): Boolean = { - @tailrec def reachableImpl(check: List[MethodNode], visited: Set[MethodNode]): Boolean = check match { - case x :: xs => + def isReachable(start: Set[MethodNode], goal: MethodNode): Boolean = { + @tailrec def reachableImpl(check: Set[MethodNode], visited: Set[MethodNode]): Boolean = { + if (check.isEmpty) false + else { + val x = check.head if (x == goal) true - else if (visited(x)) reachableImpl(xs, visited) + else if (visited(x)) reachableImpl(check - x, visited) else { - val callees = nonElidedRequests(x).map(_.callsite.callee.get.callee) - reachableImpl(xs ::: callees.toList, visited + x) + val callees = nonElidedRequests(x).flatMap(allCallees) + reachableImpl(check - x ++ callees, visited + x) } - - case Nil => - false + } } - reachableImpl(List(start), Set.empty) + reachableImpl(start, Set.empty) } val result = new mutable.ListBuffer[InlineRequest]() @@ -136,7 +138,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { java.util.Arrays.sort(requests, callsiteOrdering) for (r <- requests) { // is there a chain of inlining requests that would inline the callsite method into the callee? - if (isReachable(r.callsite.callee.get.callee, r.callsite.callsiteMethod)) + if (isReachable(allCallees(r), r.callsite.callsiteMethod)) elided += r else result += r @@ -150,8 +152,8 @@ class Inliner[BT <: BTypes](val btypes: BT) { if (requests.isEmpty) Nil else { val (leaves, others) = requests.partition(r => { - val inlineRequestsForCallee = nonElidedRequests(r.callsite.callee.get.callee) - inlineRequestsForCallee.forall(visited) + val inlineRequestsForCallees = allCallees(r).flatMap(nonElidedRequests) + inlineRequestsForCallees.forall(visited) }) assert(leaves.nonEmpty, requests) leaves ::: leavesFirst(others, visited ++ leaves) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala index 009742501e9e..79e74f3eb76c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala @@ -7,14 +7,14 @@ package scala.tools.nsc package backend.jvm package opt -import scala.tools.asm.tree.MethodNode -import scala.tools.nsc.backend.jvm.BTypes.InternalName import scala.collection.JavaConverters._ +import scala.tools.asm.Opcodes +import scala.tools.asm.tree.{MethodInsnNode, MethodNode} +import scala.tools.nsc.backend.jvm.BTypes.InternalName import scala.tools.nsc.backend.jvm.BackendReporting.OptimizerWarning class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { import bTypes._ - import inliner._ import callGraph._ case class InlineRequest(callsite: Callsite, post: List[InlineRequest], reason: String) { @@ -93,7 +93,27 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { val callee = callsite.callee.get def requestIfCanInline(callsite: Callsite, reason: String): Either[OptimizerWarning, InlineRequest] = inliner.earlyCanInlineCheck(callsite) match { case Some(w) => Left(w) - case None => Right(InlineRequest(callsite, Nil, reason)) + case None => + val callee = callsite.callee.get + val postInlineRequest: List[InlineRequest] = callee.calleeDeclarationClass.isInterface match { + case Right(true) => + // Treat the pair of trait interface method and static method as one for the purposes of inlining: + // if we inline invokeinterface, invoke the invokestatic, too. + val calls = callee.callee.instructions.iterator().asScala.filter(BytecodeUtils.isCall).take(2).toList + calls match { + case List(x: MethodInsnNode) if x.getOpcode == Opcodes.INVOKESTATIC && x.name == (callee.callee.name + "$") => + callGraph.addIfMissing(callee.callee, callee.calleeDeclarationClass) + val maybeNodeToCallsite1 = callGraph.findCallSite(callee.callee, x) + maybeNodeToCallsite1.toList.flatMap(x => requestIfCanInline(x, reason).right.toOption) + case _ => + Nil + + } + case _ => Nil + } + + Right(InlineRequest(callsite, postInlineRequest, reason)) + } compilerSettings.YoptInlineHeuristics.value match { diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 2dd8def53e13..804bcddb7b88 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -261,7 +261,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre def pretransform(tree: Tree): Tree = tree match { case dd: DefDef if dd.symbol.isDelambdafyTarget => if (!dd.symbol.hasFlag(STATIC) && methodReferencesThis(dd.symbol)) { - gen.mkStatic(dd, sym => sym) + gen.mkStatic(dd, dd.symbol.name, sym => sym) } else { dd.symbol.setFlag(STATIC) dd @@ -276,8 +276,10 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre case dd: DefDef if dd.symbol.isLiftedMethod && !dd.symbol.isDelambdafyTarget => // SI-9390 emit lifted methods that don't require a `this` reference as STATIC // delambdafy targets are excluded as they are made static by `transformFunction`. - if (!dd.symbol.hasFlag(STATIC) && !methodReferencesThis(dd.symbol)) + if (!dd.symbol.hasFlag(STATIC) && !methodReferencesThis(dd.symbol)) { dd.symbol.setFlag(STATIC) + dd.symbol.removeAttachment[mixer.NeedStaticImpl.type] + } super.transform(tree) case Apply(fun, outer :: rest) if shouldElideOuterArg(fun.symbol, outer) => val nullOuter = gen.mkZero(outer.tpe) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 6df0b992ed49..d62b77dac26e 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -130,6 +130,10 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ def addMember(clazz: Symbol, member: Symbol): Symbol = { debuglog(s"mixing into $clazz: ${member.defString}") + // This attachment is used to instruct the backend about which methids in traits require + // a static trait impl method. We remove this from the new symbol created for the method + // mixed into the subclass. + member.removeAttachment[NeedStaticImpl.type] clazz.info.decls enter member setFlag MIXEDIN resetFlag JAVA_DEFAULTMETHOD } def cloneAndAddMember(mixinClass: Symbol, mixinMember: Symbol, clazz: Symbol): Symbol = @@ -344,6 +348,10 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { reporter.error(clazz.pos, "Member %s of mixin %s is missing a concrete super implementation.".format( mixinMember.alias, mixinClass)) case alias1 => + if (alias1.owner.isJavaDefined && alias1.owner.isInterface && !clazz.parentSymbols.contains(alias1.owner)) { + val suggestedParent = exitingTyper(clazz.info.baseType(alias1.owner)) + reporter.error(clazz.pos, s"Unable to implement a super accessor required by trait ${mixinClass.name} unless $suggestedParent is directly extended by $clazz.") + } superAccessor.asInstanceOf[TermSymbol] setAlias alias1 } } @@ -1001,13 +1009,20 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val parents1 = currentOwner.info.parents map (t => TypeTree(t) setPos tree.pos) // mark fields which can be nulled afterward lazyValNullables = nullableFields(templ) withDefaultValue Set() + // Remove bodies of accessors in traits - TODO: after PR #5141 (fields refactoring), this might be a no-op val bodyEmptyAccessors = if (!sym.enclClass.isTrait) body else body mapConserve { case dd: DefDef if dd.symbol.isAccessor && !dd.symbol.isLazy => deriveDefDef(dd)(_ => EmptyTree) case tree => tree } // add all new definitions to current class or interface - treeCopy.Template(tree, parents1, self, addNewDefs(currentOwner, bodyEmptyAccessors)) + val body1 = addNewDefs(currentOwner, bodyEmptyAccessors) + body1 foreach { + case dd: DefDef if isTraitMethodRequiringStaticImpl(dd) => + dd.symbol.updateAttachment(NeedStaticImpl) + case _ => + } + treeCopy.Template(tree, parents1, self, body1) case Select(qual, name) if sym.owner.isTrait && !sym.isMethod => // refer to fields in some trait an abstract getter in the interface. @@ -1023,7 +1038,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { typedPos(tree.pos)((qual DOT setter)(rhs)) - case _ => tree } @@ -1042,4 +1056,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { finally localTyper = saved } } + + private def isTraitMethodRequiringStaticImpl(dd: DefDef): Boolean = { + val sym = dd.symbol + dd.rhs.nonEmpty && + sym.owner.isTrait && + !sym.isPrivate && // no need to put implementations of private methods into a static method + !sym.hasFlag(Flags.STATIC) + } + + case object NeedStaticImpl extends PlainAttachment } diff --git a/test/files/instrumented/InstrumentationTest.check b/test/files/instrumented/InstrumentationTest.check index 74f9c9d26885..d317fc42077d 100644 --- a/test/files/instrumented/InstrumentationTest.check +++ b/test/files/instrumented/InstrumentationTest.check @@ -6,5 +6,5 @@ Method call statistics: 1 instrumented/Foo2.someMethod()I 1 scala/DeprecatedConsole.()V 1 scala/Predef$.println(Ljava/lang/Object;)V - 1 scala/io/AnsiColor.$init$()V + 1 scala/io/AnsiColor.$init$(Lscala/io/AnsiColor;)V 1 scala/runtime/BoxesRunTime.boxToBoolean(Z)Ljava/lang/Boolean; diff --git a/test/files/neg/trait-defaults-super.check b/test/files/neg/trait-defaults-super.check new file mode 100644 index 000000000000..2b19402828b5 --- /dev/null +++ b/test/files/neg/trait-defaults-super.check @@ -0,0 +1,4 @@ +trait-defaults-super.scala:14: error: Unable to implement a super accessor required by trait T unless Iterable[String] is directly extended by class C. +class C extends T + ^ +one error found diff --git a/test/files/neg/trait-defaults-super.scala b/test/files/neg/trait-defaults-super.scala new file mode 100644 index 000000000000..def271e8e747 --- /dev/null +++ b/test/files/neg/trait-defaults-super.scala @@ -0,0 +1,21 @@ +trait T extends java.lang.Iterable[String] { + + override def spliterator(): java.util.Spliterator[String] = { + super[Iterable].spliterator + super.spliterator + null + } + def foo = { + super[Iterable].spliterator + super.spliterator + } + def iterator(): java.util.Iterator[String] = java.util.Collections.emptyList().iterator() +} +class C extends T +object Test { + def main(args: Array[String]): Unit = { + val t: T = new C + t.spliterator + t.foo + } +} diff --git a/test/files/pos/trait-defaults-super.scala b/test/files/pos/trait-defaults-super.scala new file mode 100644 index 000000000000..8f867ab5632d --- /dev/null +++ b/test/files/pos/trait-defaults-super.scala @@ -0,0 +1,21 @@ +trait T extends java.lang.Iterable[String] { + + override def spliterator(): java.util.Spliterator[String] = { + super[Iterable].spliterator + super.spliterator + null + } + def foo = { + super[Iterable].spliterator + super.spliterator + } + def iterator(): java.util.Iterator[String] = java.util.Collections.emptyList().iterator() +} +class C extends T with java.lang.Iterable[String] // super accessor is okay with Iterable as a direct parent +object Test { + def main(args: Array[String]): Unit = { + val t: T = new C + t.spliterator + t.foo + } +} diff --git a/test/files/run/t4891.check b/test/files/run/t4891.check index 1b1108e9eee0..a460569fd9dc 100644 --- a/test/files/run/t4891.check +++ b/test/files/run/t4891.check @@ -1,6 +1,7 @@ test.generic.T1 - (m) public default void test.generic.T1.$init$() + (m) public static void test.generic.T1.$init$(test.generic.T1) (m) public default A test.generic.T1.t1(A) + (m) public static java.lang.Object test.generic.T1.t1$(test.generic.T1,java.lang.Object) test.generic.C1 (m) public void test.generic.C1.m1() test.generic.C2 diff --git a/test/files/run/t5652.check b/test/files/run/t5652.check index 7c65ba66981d..3c039d68aa7c 100644 --- a/test/files/run/t5652.check +++ b/test/files/run/t5652.check @@ -1,6 +1,7 @@ public default int T1.f0() -public default void T1.$init$() public static int T1.T1$$g$1() +public static int T1.f0$(T1) +public static void T1.$init$(T1) public int A1.f1() public static final int A1.A1$$g$2() public int A2.f2() diff --git a/test/files/run/t7700.check b/test/files/run/t7700.check index 1d51e68877ca..7d18dbfcb4e9 100644 --- a/test/files/run/t7700.check +++ b/test/files/run/t7700.check @@ -1,3 +1,4 @@ -public default void C.$init$() +public static void C.$init$(C) public default java.lang.Object C.bar(java.lang.Object) -public abstract java.lang.Object C.foo(java.lang.Object) +public static java.lang.Object C.bar$(C,java.lang.Object) +public abstract java.lang.Object C.foo(java.lang.Object) \ No newline at end of file diff --git a/test/files/run/t7700.scala b/test/files/run/t7700.scala index 76d16b808c52..fd13666467f8 100644 --- a/test/files/run/t7700.scala +++ b/test/files/run/t7700.scala @@ -7,11 +7,13 @@ trait C[@specialized U] { def bar[A](u: U) = u } -object Test extends App { - val declared = classOf[C[_]].getDeclaredMethods.sortBy(_.getName) - println(declared.mkString("\n")) - object CInt extends C[Int] { def foo(i: Int) = i } - object CAny extends C[Any] { def foo(a: Any) = a } - assert(CInt.foo(1) == 1) - assert(CAny.foo("") == "") +object Test { + def main(args: Array[String]) { + val declared = classOf[C[_]].getDeclaredMethods.sortBy(_.getName) + println(declared.mkString("\n")) + object CInt extends C[Int] { def foo(i: Int) = i } + object CAny extends C[Any] { def foo(a: Any) = a } + assert(CInt.foo(1) == 1) + assert(CAny.foo("") == "") + } } diff --git a/test/files/run/t7932.check b/test/files/run/t7932.check index a2ad84cd4635..76968fd179ca 100644 --- a/test/files/run/t7932.check +++ b/test/files/run/t7932.check @@ -2,5 +2,9 @@ public Category C.category() public Category C.category1() public default Category M1.category() public default Category M1.category1() +public static Category M1.category$(M1) +public static Category M1.category1$(M1) public default Category M2.category() public default Category M2.category1() +public static Category M2.category$(M2) +public static Category M2.category1$(M2) \ No newline at end of file diff --git a/test/files/run/t7932.scala b/test/files/run/t7932.scala index e6bdbf24170c..40b0b9989b53 100644 --- a/test/files/run/t7932.scala +++ b/test/files/run/t7932.scala @@ -17,12 +17,14 @@ trait M2[F] { self: M1[F] => abstract class C extends M1[Float] with M2[Float] -object Test extends App { +object Test { def t(c: Class[_]) = { val ms = c.getMethods.filter(_.getName.startsWith("category")) println(ms.map(_.toGenericString).sorted.mkString("\n")) } - t(classOf[C]) - t(classOf[M1[_]]) - t(classOf[M2[_]]) + def main(args: Array[String]) { + t(classOf[C]) + t(classOf[M1[_]]) + t(classOf[M2[_]]) + } } diff --git a/test/files/run/trait-static-clash.scala b/test/files/run/trait-static-clash.scala new file mode 100644 index 000000000000..603cf6b6e544 --- /dev/null +++ b/test/files/run/trait-static-clash.scala @@ -0,0 +1,10 @@ +trait T { + def foo = 1 + def foo(t: T) = 2 +} +object Test extends T { + def main(args: Array[String]) { + assert(foo == 1) + assert(foo(this) == 2) + } +} diff --git a/test/junit/scala/lang/traits/BytecodeTest.scala b/test/junit/scala/lang/traits/BytecodeTest.scala index f47fc9c12724..ec8508df999e 100644 --- a/test/junit/scala/lang/traits/BytecodeTest.scala +++ b/test/junit/scala/lang/traits/BytecodeTest.scala @@ -9,6 +9,7 @@ import scala.collection.JavaConverters._ import scala.tools.asm.Opcodes import scala.tools.asm.Opcodes._ import scala.tools.asm.tree.ClassNode +import scala.tools.nsc.backend.jvm.opt.BytecodeUtils import scala.tools.partest.ASMConverters._ import scala.tools.testing.BytecodeTesting import scala.tools.testing.BytecodeTesting._ @@ -18,8 +19,8 @@ class BytecodeTest extends BytecodeTesting { import compiler._ def checkForwarder(classes: Map[String, ClassNode], clsName: Symbol, target: String) = { - val List(f) = getMethods(classes(clsName.name), "f") - assertSameCode(f, List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, target, "f", "()I", false), Op(IRETURN))) + val f = getMethod(classes(clsName.name), "f") + assertSameCode(f, List(VarOp(ALOAD, 0), Invoke(INVOKESTATIC, target, "f$", s"(L$target;)I", true), Op(IRETURN))) } @Test @@ -88,7 +89,7 @@ class BytecodeTest extends BytecodeTesting { assertSameSummary(getMethod(c("C18"), "f"), List(BIPUSH, IRETURN)) checkForwarder(c, 'C19, "T7") assertSameCode(getMethod(c("C19"), "T7$$super$f"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "C18", "f", "()I", false), Op(IRETURN))) - assertInvoke(getMethod(c("C20"), "clone"), "T8", "clone") // mixin forwarder + assertInvoke(getMethod(c("C20"), "clone"), "T8", "clone$") // mixin forwarder } @Test @@ -141,7 +142,7 @@ class BytecodeTest extends BytecodeTesting { def invocationReceivers(): Unit = { val List(c1, c2, t, u) = compileClasses(invocationReceiversTestCode.definitions("Object")) // mixin forwarder in C1 - assertSameCode(getMethod(c1, "clone"), List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "T", "clone", "()Ljava/lang/Object;", false), Op(ARETURN))) + assertSameCode(getMethod(c1, "clone"), List(VarOp(ALOAD, 0), Invoke(INVOKESTATIC, "T", "clone$", "(LT;)Ljava/lang/Object;", true), Op(ARETURN))) assertInvoke(getMethod(c1, "f1"), "T", "clone") assertInvoke(getMethod(c1, "f2"), "T", "clone") assertInvoke(getMethod(c1, "f3"), "C1", "clone") diff --git a/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala index c9a958ee4f4d..841e850b491b 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DefaultMethodTest.scala @@ -5,6 +5,7 @@ import org.junit.Test import scala.collection.JavaConverters import scala.collection.JavaConverters._ +import scala.reflect.internal.Flags import scala.tools.asm.Opcodes import scala.tools.asm.tree.ClassNode import scala.tools.testing.BytecodeTesting @@ -21,7 +22,7 @@ class DefaultMethodTest extends BytecodeTesting { /** Transforms a single tree. */ override def transform(tree: global.Tree): global.Tree = tree match { case dd @ DefDef(_, Foo, _, _, _, _) => - dd.symbol.setFlag(reflect.internal.Flags.JAVA_DEFAULTMETHOD) + dd.symbol.setFlag(Flags.JAVA_DEFAULTMETHOD).resetFlag(Flags.DEFERRED) copyDefDef(dd)(rhs = Literal(Constant(1)).setType(definitions.IntTpe)) case _ => super.transform(tree) } @@ -31,6 +32,4 @@ class DefaultMethodTest extends BytecodeTesting { assertTrue("default method should not be abstract", (foo.access & Opcodes.ACC_ABSTRACT) == 0) assertTrue("default method body emitted", foo.instructions.size() > 0) } - - } diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala index a28599cd9212..38285fbce1fb 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala @@ -1,7 +1,9 @@ package scala.tools.nsc.backend.jvm +import java.nio.file.{Files, Paths} + import org.junit.Assert._ -import org.junit.Test +import org.junit.{Ignore, Test} import org.junit.runner.RunWith import org.junit.runners.JUnit4 diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala index a2513cacdc47..85df42e0695d 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala @@ -97,7 +97,7 @@ class InlinerSeparateCompilationTest { """.stripMargin val List(a, t) = compileClassesSeparately(List(codeA, assembly), args) - assertNoInvoke(getMethod(t, "f")) - assertNoInvoke(getMethod(a, "n")) + assertNoInvoke(getMethod(t, "f$")) + assertNoInvoke(getMethod(a, "n$")) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala index 9173a1d1893e..f531ce932238 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -475,11 +475,9 @@ class InlinerTest extends BytecodeTesting { | def t2 = this.f |} """.stripMargin - val warns = Set( - "C::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden", - "T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden") + val warn = "T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" var count = 0 - val List(c, t) = compile(code, allowMessage = i => {count += 1; warns.exists(i.msg contains _)}) + val List(c, t) = compile(code, allowMessage = i => {count += 1; i.msg contains warn}) assert(count == 2, count) assertInvoke(getMethod(c, "t1"), "T", "f") assertInvoke(getMethod(c, "t2"), "C", "f") @@ -520,7 +518,7 @@ class InlinerTest extends BytecodeTesting { val List(c, oMirror, oModule, t) = compile(code, allowMessage = i => {count += 1; i.msg contains warn}) assert(count == 1, count) - assertNoInvoke(getMethod(t, "f")) + assertNoInvoke(getMethod(t, "f$")) assertNoInvoke(getMethod(c, "t1")) assertNoInvoke(getMethod(c, "t2")) @@ -546,9 +544,9 @@ class InlinerTest extends BytecodeTesting { val List(assembly, c, t) = compile(code) - assertNoInvoke(getMethod(t, "f")) + assertNoInvoke(getMethod(t, "f$")) - assertNoInvoke(getMethod(assembly, "n")) + assertNoInvoke(getMethod(assembly, "n$")) assertNoInvoke(getMethod(c, "t1")) assertNoInvoke(getMethod(c, "t2")) @@ -624,8 +622,8 @@ class InlinerTest extends BytecodeTesting { val List(ca, cb, t1, t2a, t2b) = compile(code, allowMessage = i => {count += 1; i.msg contains warning}) assert(count == 4, count) // see comments, f is not inlined 4 times - assertNoInvoke(getMethod(t2a, "g2a")) - assertInvoke(getMethod(t2b, "g2b"), "T1", "f") + assertNoInvoke(getMethod(t2a, "g2a$")) + assertInvoke(getMethod(t2b, "g2b$"), "T1", "f") assertInvoke(getMethod(ca, "m1a"), "T1", "f") assertNoInvoke(getMethod(ca, "m2a")) // no invoke, see comment on def g2a @@ -684,8 +682,8 @@ class InlinerTest extends BytecodeTesting { |} """.stripMargin val List(c, t) = compile(code) - val t1 = getMethod(t, "t1") - val t2 = getMethod(t, "t2") + val t1 = getMethod(t, "t1$") + val t2 = getMethod(t, "t2$") val cast = TypeOp(CHECKCAST, "C") Set(t1, t2).foreach(m => assert(m.instructions.contains(cast), m.instructions)) } @@ -1574,4 +1572,19 @@ class InlinerTest extends BytecodeTesting { Label(0), LineNumber(9, Label(0)), VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "C", "fx", "()V", false), Label(4), LineNumber(10, Label(4)), Op(ICONST_1), Op(IRETURN), Label(8))) } + + @Test + def traitHO(): Unit = { + val code = + """trait T { + | def foreach(f: Int => Unit): Unit = f(1) + |} + |final class C extends T { + | def cons(x: Int): Unit = () + | def t1 = foreach(cons) + |} + """.stripMargin + val List(c, t) = compile(code) + assertNoIndy(getMethod(c, "t1")) + } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala index 4791a29bfbb7..54f4c805c1d1 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala @@ -31,6 +31,14 @@ class ScalaInlineInfoTest extends BytecodeTesting { r.toString } + def assertSameMethods(c: ClassNode, nameAndSigs: Set[String]): Unit = { + val r = new StringBuilder + val inClass = c.methods.iterator.asScala.map(m => m.name + m.desc).toSet + for (m <- inClass.diff(nameAndSigs)) r.append(s"method in classfile found, but no inline info: $m") + for (m <- nameAndSigs.diff(inClass)) r.append(s"inline info found, but no method in classfile: $m") + assert(r.isEmpty, r.toString) + } + @Test def traitMembersInlineInfo(): Unit = { val code = @@ -79,26 +87,32 @@ class ScalaInlineInfoTest extends BytecodeTesting { ("T$$super$toString()Ljava/lang/String;", MethodInlineInfo(true ,false,false)), ("T$_setter_$x1_$eq(I)V", MethodInlineInfo(false,false,false)), ("f1()I", MethodInlineInfo(false,false,false)), - ("f2()I", MethodInlineInfo(true, false,false)), + ("f1$(LT;)I", MethodInlineInfo(true ,false,false)), + ("f2()I", MethodInlineInfo(true ,false,false)), // no static impl method for private method f2 ("f3()I", MethodInlineInfo(false,false,false)), + ("f3$(LT;)I", MethodInlineInfo(true ,false,false)), ("f4()Ljava/lang/String;", MethodInlineInfo(false,true, false)), + ("f4$(LT;)Ljava/lang/String;", MethodInlineInfo(true ,true, false)), ("f5()I", MethodInlineInfo(true ,false,false)), - ("f6()I", MethodInlineInfo(false,false,true )), + ("f5$(LT;)I", MethodInlineInfo(true ,false,false)), + ("f6()I", MethodInlineInfo(false,false,true )), // no static impl method for abstract method f6 ("x1()I", MethodInlineInfo(false,false,false)), ("y2()I", MethodInlineInfo(false,false,false)), ("y2_$eq(I)V", MethodInlineInfo(false,false,false)), ("x3()I", MethodInlineInfo(false,false,false)), ("x3_$eq(I)V", MethodInlineInfo(false,false,false)), ("x4()I", MethodInlineInfo(false,false,false)), + ("x4$(LT;)I", MethodInlineInfo(true ,false,false)), ("x5()I", MethodInlineInfo(true, false,false)), ("L$lzycompute$1(Lscala/runtime/VolatileObjectRef;)LT$L$2$;", MethodInlineInfo(true, false,false)), ("L$1(Lscala/runtime/VolatileObjectRef;)LT$L$2$;", MethodInlineInfo(true ,false,false)), ("nest$1()I", MethodInlineInfo(true, false,false)), - ("$init$()V", MethodInlineInfo(false,false,false))), + ("$init$(LT;)V", MethodInlineInfo(true,false,false))), None // warning ) assert(infoT == expectT, mapDiff(expectT.methodInfos, infoT.methodInfos) + infoT) + assertSameMethods(t, expectT.methodInfos.keySet) val infoC = inlineInfo(c) val expectC = InlineInfo(false, None, Map( @@ -119,6 +133,7 @@ class ScalaInlineInfoTest extends BytecodeTesting { None) assert(infoC == expectC, mapDiff(expectC.methodInfos, infoC.methodInfos) + infoC) + assertSameMethods(c, expectC.methodInfos.keySet) } @Test @@ -156,7 +171,6 @@ class ScalaInlineInfoTest extends BytecodeTesting { ("F",None), ("T",Some("h(Ljava/lang/String;)I")), ("U",None))) - } @Test @@ -169,5 +183,6 @@ class ScalaInlineInfoTest extends BytecodeTesting { "O$lzycompute()LC$O$;" -> MethodInlineInfo(true,false,false), "O()LC$O$;" -> MethodInlineInfo(true,false,false)) assert(infoC.methodInfos == expected, mapDiff(infoC.methodInfos, expected)) + assertSameMethods(c, expected.keySet) } } diff --git a/test/junit/scala/tools/testing/BytecodeTesting.scala b/test/junit/scala/tools/testing/BytecodeTesting.scala index 4ddb6580df9e..c0fdb8010f84 100644 --- a/test/junit/scala/tools/testing/BytecodeTesting.scala +++ b/test/junit/scala/tools/testing/BytecodeTesting.scala @@ -12,6 +12,7 @@ import scala.tools.asm.tree.{AbstractInsnNode, ClassNode, MethodNode} import scala.tools.cmd.CommandLineParser import scala.tools.nsc.backend.jvm.AsmUtils import scala.tools.nsc.backend.jvm.AsmUtils._ +import scala.tools.nsc.backend.jvm.opt.BytecodeUtils import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.reporters.StoreReporter import scala.tools.nsc.{Global, Settings} @@ -247,11 +248,19 @@ object BytecodeTesting { def getAsmMethod(c: ClassNode, name: String): MethodNode = { val methods = getAsmMethods(c, name) + def fail() = { + val allNames = getAsmMethods(c, _ => true).map(_.name) + throw new AssertionFailedError(s"Could not find method named $name among ${allNames}") + } methods match { case List(m) => m - case ms => - val allNames = getAsmMethods(c, _ => true).map(_.name) - throw new AssertionFailedError(s"Could not find method named $name among ${allNames}") + case ms @ List(m1, m2) if BytecodeUtils.isInterface(c) => + val (statics, nonStatics) = ms.partition(BytecodeUtils.isStaticMethod) + (statics, nonStatics) match { + case (List(staticMethod), List(_)) => m1 // prefer the static method of the pair if methods in traits + case _ => fail() + } + case ms => fail() } } From 9901daf6dcd78fb0a5b359d1c9549114ce23aa0c Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 28 Jun 2016 09:54:30 -0700 Subject: [PATCH 119/153] Bootstrap skips scalacheck build step / partest dep Keeping diff minimal since this will need to be reverted once 2.12.0 is final. --- scripts/jobs/integrate/bootstrap | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index 76673b4f32c5..7716dc9eb1c1 100644 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -247,7 +247,7 @@ buildPartest() { else update scala scala-partest "$PARTEST_REF" && gfxd doc="$(docTask $PARTEST_BUILT)" - sbtBuild 'set version :="'$PARTEST_VER'"' 'set VersionKeys.scalaXmlVersion := "'$XML_VER'"' 'set VersionKeys.scalaCheckVersion := "'$SCALACHECK_VER'"' $clean "$doc" test "${buildTasks[@]}" + sbtBuild 'set version :="'$PARTEST_VER'"' 'set VersionKeys.scalaXmlVersion := "'$XML_VER'"' $clean "$doc" test "${buildTasks[@]}" PARTEST_BUILT="yes" fi } @@ -282,7 +282,7 @@ buildModules() { buildXML buildParsers buildSwing - buildScalacheck + # buildScalacheck buildPartest } @@ -424,7 +424,7 @@ deriveModuleVersions() { echo "Module versions (versioning strategy: $moduleVersioning):" echo "PARSERS = $PARSERS_VER at $PARSERS_REF" echo "PARTEST = $PARTEST_VER at $PARTEST_REF" - echo "SCALACHECK = $SCALACHECK_VER at $SCALACHECK_REF" + # echo "SCALACHECK = $SCALACHECK_VER at $SCALACHECK_REF" echo "SWING = $SWING_VER at $SWING_REF" echo "XML = $XML_VER at $XML_REF" @@ -444,7 +444,7 @@ removeExistingBuilds() { local storageApiUrl=`echo $releaseTempRepoUrl | sed 's/\(scala-release-temp\)/api\/storage\/\1/'` local scalaLangModules=`curl -s $storageApiUrl/org/scala-lang | jq -r '.children | .[] | "org/scala-lang" + .uri' | grep -v actors-migration` - for module in "org/scalacheck" $scalaLangModules; do + for module in $scalaLangModules; do local artifacts=`curl -s $storageApiUrl/$module | jq -r ".children | .[] | select(.uri | contains(\"$SCALA_VER\")) | .uri"` for artifact in $artifacts; do echo "Deleting $releaseTempRepoUrl$module$artifact" @@ -464,7 +464,7 @@ constructUpdatedModuleVersions() { updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala-xml.version.number=$XML_VER") updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dpartest.version.number=$PARTEST_VER") - updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscalacheck.version.number=$SCALACHECK_VER") + # updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscalacheck.version.number=$SCALACHECK_VER") # allow overriding the jline version using a jenkins build parameter if [ ! -z "$JLINE_VER" ] ; then updatedModuleVersions=("${updatedModuleVersions[@]}" "-Djline.version=$JLINE_VER"); fi From d8c862b225cc7936e475419abaabb07226fea568 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 28 Jun 2016 18:01:14 -0700 Subject: [PATCH 120/153] Use 2.12.0-M4-9901daf as STARR (see #5152) This commit switches to using 2.12.0-M3-dc9effe as STARR, so that we can switch to the new trait encoding where each concrete trait member gets a a static member, which has the actual implementation (as well as serving as a target for for super calls using invokestatic), and a default member (forwards to the static member). Also bump partest to 1.0.17 -- the release that goes with the in-sourcing of scalacheck. Replace a few more -Yopt with -opt (for our new STARR) --- project/ScriptCommands.scala | 2 +- test/benchmarks/build.sbt | 2 +- versions.properties | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/project/ScriptCommands.scala b/project/ScriptCommands.scala index e5ff38617eab..0bf43b18e872 100644 --- a/project/ScriptCommands.scala +++ b/project/ScriptCommands.scala @@ -13,7 +13,7 @@ object ScriptCommands { // Append build.timestamp to Artifactory URL to get consistent build numbers (see https://github.com/sbt/sbt/issues/2088): publishTo in Global := Some("scala-pr" at url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis), publishArtifact in (Compile, packageDoc) in ThisBuild := false, - scalacOptions in Compile in ThisBuild += "-Yopt:l:classpath", + scalacOptions in Compile in ThisBuild += "-opt:l:classpath", logLevel in ThisBuild := Level.Info, logLevel in update in ThisBuild := Level.Warn ), state) diff --git a/test/benchmarks/build.sbt b/test/benchmarks/build.sbt index 31cee701ad61..fb05fb2c99f1 100644 --- a/test/benchmarks/build.sbt +++ b/test/benchmarks/build.sbt @@ -1,6 +1,6 @@ scalaHome := Some(file("../../build/pack")) scalaVersion := "2.12.0-dev" -scalacOptions ++= Seq("-feature", "-Yopt:l:classpath") +scalacOptions ++= Seq("-feature", "-opt:l:classpath") lazy val root = (project in file(".")). enablePlugins(JmhPlugin). diff --git a/versions.properties b/versions.properties index 3b8077ab885b..bf7c7d2faaad 100644 --- a/versions.properties +++ b/versions.properties @@ -8,7 +8,7 @@ # The scala version used for bootstrapping. This has no impact on the final classfiles: # there are two stages (locker and quick), so compiler and library are always built # with themselves. Stability is ensured by building a third stage (strap). -starr.version=2.12.0-M4 +starr.version=2.12.0-M4-9901daf # These are the versions of the modules that go with this release. # These properties are used during PR validation and in dbuild builds. @@ -19,7 +19,7 @@ starr.version=2.12.0-M4 # - After 2.x.0 is released, the binary version is 2.x. # - During milestones and RCs, modules are cross-built against the full version. # So the value is the full version (e.g. 2.12.0-M2). -scala.binary.version=2.12.0-M4 +scala.binary.version=2.12.0-M4-9901daf # external modules shipped with distribution, as specified by scala-library-all's pom scala-xml.version.number=1.0.5 @@ -30,7 +30,7 @@ jline.version=2.14.1 scala-asm.version=5.0.4-scala-3 # external modules, used internally (not shipped) -partest.version.number=1.0.16 +partest.version.number=1.0.17 # We've embedded these sources in partest-extras for now. After 2.12.0 is released # we can switch to a public release. # scalacheck.version.number=1.11.6 From de59237938abf34c8a22f57bb99a27f1837c6333 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 29 Jun 2016 15:23:12 -0700 Subject: [PATCH 121/153] Bump STARR to 2.12.0-M5. --- versions.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/versions.properties b/versions.properties index bf7c7d2faaad..4d24e0d598af 100644 --- a/versions.properties +++ b/versions.properties @@ -8,7 +8,7 @@ # The scala version used for bootstrapping. This has no impact on the final classfiles: # there are two stages (locker and quick), so compiler and library are always built # with themselves. Stability is ensured by building a third stage (strap). -starr.version=2.12.0-M4-9901daf +starr.version=2.12.0-M5 # These are the versions of the modules that go with this release. # These properties are used during PR validation and in dbuild builds. @@ -19,7 +19,7 @@ starr.version=2.12.0-M4-9901daf # - After 2.x.0 is released, the binary version is 2.x. # - During milestones and RCs, modules are cross-built against the full version. # So the value is the full version (e.g. 2.12.0-M2). -scala.binary.version=2.12.0-M4-9901daf +scala.binary.version=2.12.0-M5 # external modules shipped with distribution, as specified by scala-library-all's pom scala-xml.version.number=1.0.5 From e5886361006f1b315af13f6aa98cf54a2f7ebe0b Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 4 Jul 2016 16:45:01 +0200 Subject: [PATCH 122/153] SI-9515 closure elimination also for non-Scala-Function SAM types Also logged in as SD-162 The optimizer had conservative checks in place to perform closure elimination only for Scala Function types. We can eliminate IndyLambda instructions for any functional interface. LambdaMetaFactory only constructs lambda objects for interface types, which don't have any side-effects on construction - they don't have a constructor. --- .../tools/nsc/backend/jvm/CoreBTypes.scala | 24 ------------------- .../backend/jvm/analysis/BackendUtils.scala | 3 --- .../tools/nsc/backend/jvm/opt/CallGraph.scala | 2 +- .../tools/nsc/backend/jvm/opt/CopyProp.scala | 14 ++++------- .../backend/jvm/opt/MethodLevelOptsTest.scala | 20 ++++++++++++++++ 5 files changed, 25 insertions(+), 38 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index 1feca56923f4..d65380aa1fc7 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -217,26 +217,6 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { nonOverloadedConstructors(tupleClassSymbols) } - // enumeration of specialized classes is temporary, while we still use the java-defined JFunctionN. - // once we switch to ordinary FunctionN, we can use specializedSubclasses just like for tuples. - private def specializedJFunctionSymbols(base: String): Seq[Symbol] = { - def primitives = Seq("B", "S", "I", "J", "C", "F", "D", "Z", "V") - def ijfd = Iterator("I", "J", "F", "D") - def ijfdzv = Iterator("I", "J", "F", "D", "Z", "V") - def ijd = Iterator("I", "J", "D") - val classNames = { - primitives.map(base + "0$mc" + _ + "$sp") // Function0 - } ++ { - // return type specializations appear first in the name string (alphabetical sorting) - for (r <- ijfdzv; a <- ijfd) yield base + "1$mc" + r + a + "$sp" // Function1 - } ++ { - for (r <- ijfdzv; a <- ijd; b <- ijd) yield base + "2$mc" + r + a + b + "$sp" // Function2 - } - classNames map getRequiredClass - } - - lazy val functionRefs: Set[InternalName] = (FunctionClass.seq ++ specializedJFunctionSymbols("scala.runtime.java8.JFunction")).map(classBTypeFromSymbol(_).internalName).toSet - lazy val typeOfArrayOp: Map[Int, BType] = { import scalaPrimitives._ Map( @@ -342,8 +322,6 @@ trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] { def srRefConstructors : Map[InternalName, MethodNameAndType] def tupleClassConstructors : Map[InternalName, MethodNameAndType] - def functionRefs: Set[InternalName] - def lambdaMetaFactoryBootstrapHandle : asm.Handle def lambdaDeserializeBootstrapHandle : asm.Handle } @@ -410,8 +388,6 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def srRefConstructors : Map[InternalName, MethodNameAndType] = _coreBTypes.srRefConstructors def tupleClassConstructors : Map[InternalName, MethodNameAndType] = _coreBTypes.tupleClassConstructors - def functionRefs: Set[InternalName] = _coreBTypes.functionRefs - def srSymbolLiteral : ClassBType = _coreBTypes.srSymbolLiteral def srStructuralCallSite : ClassBType = _coreBTypes.srStructuralCallSite def srLambdaDeserialize : ClassBType = _coreBTypes.srLambdaDeserialize diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index 539435a32604..83615abc31bb 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -131,7 +131,6 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { private val anonfunAdaptedName = """.*\$anonfun\$.*\$\d+\$adapted""".r def hasAdaptedImplMethod(closureInit: ClosureInstantiation): Boolean = { - isBuiltinFunctionType(Type.getReturnType(closureInit.lambdaMetaFactoryCall.indy.desc).getInternalName) && anonfunAdaptedName.pattern.matcher(closureInit.lambdaMetaFactoryCall.implMethod.getName).matches } @@ -256,8 +255,6 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { } } - def isBuiltinFunctionType(internalName: InternalName): Boolean = functionRefs(internalName) - /** * Visit the class node and collect all referenced nested classes. */ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index d6942d9ff99b..5248183337fa 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -430,7 +430,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { def unapply(insn: AbstractInsnNode): Option[(InvokeDynamicInsnNode, Type, Handle, Type)] = insn match { case indy: InvokeDynamicInsnNode if indy.bsm == metafactoryHandle || indy.bsm == altMetafactoryHandle => indy.bsmArgs match { - case Array(samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type, xs@_*) => // xs binding because IntelliJ gets confused about _@_* + case Array(samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type, _@_*) => // LambdaMetaFactory performs a number of automatic adaptations when invoking the lambda // implementation method (casting, boxing, unboxing, and primitive widening, see Javadoc). // diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala index 4163d62df77f..b05669ce899d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala @@ -295,18 +295,12 @@ class CopyProp[BT <: BTypes](val btypes: BT) { } /** - * Eliminate the closure value produced by `indy`. If the SAM type is known to construct - * without side-effects (e.g. scala/FunctionN), the `indy` and its inputs - * are eliminated, otherwise a POP is inserted. + * Eliminate LMF `indy` and its inputs. */ def handleClosureInst(indy: InvokeDynamicInsnNode): Unit = { - if (isBuiltinFunctionType(Type.getReturnType(indy.desc).getInternalName)) { - toRemove += indy - callGraph.removeClosureInstantiation(indy, method) - handleInputs(indy, Type.getArgumentTypes(indy.desc).length) - } else { - toInsertAfter(indy) = getPop(1) - } + toRemove += indy + callGraph.removeClosureInstantiation(indy, method) + handleInputs(indy, Type.getArgumentTypes(indy.desc).length) } def runQueue(): Unit = while (queue.nonEmpty) { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 938bc7b84686..2c697bfe5079 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -750,4 +750,24 @@ class MethodLevelOptsTest extends BytecodeTesting { -1, LDC, ASTORE, -1, ALOAD, ARETURN)) } + + @Test + def elimSamLambda(): Unit = { + val code = + """class C { + | def t1(x: Int) = { + | val fun: java.util.function.IntFunction[Int] = y => y + 1 + | fun(x) + | } + | def t2(x: Int) = { + | val fun: T = i => i + 1 + | fun.f(x) + | } + |} + |trait T { def f(x: Int): Int } + """.stripMargin + val List(c, t) = compileClasses(code) + assertSameSummary(getMethod(c, "t1"), List(ILOAD, "$anonfun$t1$1", IRETURN)) + assertSameSummary(getMethod(c, "t2"), List(ILOAD, "$anonfun$t2$1", IRETURN)) + } } From 1c1abd1cbb41a1e03af215eea566bd9202e1079a Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Sun, 12 Jun 2016 15:36:54 +0100 Subject: [PATCH 123/153] Fixed a typo in Predef --- src/library/scala/Predef.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 5f1a6b0bbbd5..8de9754b50c2 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -71,7 +71,7 @@ import scala.io.StdIn * * @groupname assertions Assertions * @groupprio assertions 20 - * @groupdesc assertions These methods support program verfication and runtime correctness. + * @groupdesc assertions These methods support program verification and runtime correctness. * * @groupname console-output Console Output * @groupprio console-output 30 From 27f30053c7247bacfb099dad843e5d4c6cee7816 Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Wed, 6 Jul 2016 12:42:12 +0100 Subject: [PATCH 124/153] Group math package functions Groups - Mathematical Constants - Minimum and Maximum - Rounding - Exponential and Logarithmic - Trigonometric - Angular Measurement Conversion - Hyperbolic - Absolute Values - Signs - Root Extraction - Polar Coordindates - Unit of Least Precision Other changes, - Dropped use of `double` for `Double` in all cases - Grouped some methods in the source - Extended notes about exception to method forwarding - Minor method documentation enhancements IEEERemainder is in the Rounding group since it is related to rounding and did not justify a new group. --- src/library/scala/math/package.scala | 253 ++++++++++++++++++++------- 1 file changed, 189 insertions(+), 64 deletions(-) diff --git a/src/library/scala/math/package.scala b/src/library/scala/math/package.scala index 0e39af2febd9..546efef114f1 100644 --- a/src/library/scala/math/package.scala +++ b/src/library/scala/math/package.scala @@ -11,28 +11,90 @@ package scala /** The package object `scala.math` contains methods for performing basic * numeric operations such as elementary exponential, logarithmic, root and * trigonometric functions. + * + * All methods forward to [[java.lang.Math]] unless otherwise noted. + * + * @see [[java.lang.Math]] + * + * @groupname math-const Mathematical Constants + * @groupprio math-const 10 + * + * @groupname minmax Minimum and Maximum + * @groupdesc minmax Find the min or max of two numbers. Note: [[scala.collection.TraversableOnce]] has + * min and max methods which determine the min or max of a collection. + * @groupprio minmax 20 + * + * @groupname rounding Rounding + * @groupprio rounding 30 + * + * @groupname explog Exponential and Logarithmic + * @groupprio explog 40 + * + * @groupname trig Trigonometric + * @groupdesc trig Arguments in radians + * @groupprio trig 50 + * + * @groupname angle-conversion Angular Measurement Conversion + * @groupprio angle-conversion 60 + * + * @groupname hyperbolic Hyperbolic + * @groupprio hyperbolic 70 + * + * @groupname abs Absolute Values + * @groupdesc abs Determine the magnitude of a value by discarding the sign. Results are >= 0. + * @groupprio abs 80 + * + * @groupname signum Signs + * @groupdesc signum Extract the sign of a value. Results are -1, 0 or 1. + * Note that these are not pure forwarders to the java versions. + * In particular, the return type of java.lang.Long.signum is Int, + * but here it is widened to Long so that each overloaded variant + * will return the same numeric type it is passed. + * @groupprio signum 90 + * + * @groupname root-extraction Root Extraction + * @groupprio root-extraction 100 + * + * @groupname polar-coords Polar Coordinates + * @groupprio polar-coords 110 + * + * @groupname ulp Unit of Least Precision + * @groupprio ulp 120 + * + * @groupname randomisation Pseudo Random Number Generation + * @groupprio randomisation 130 */ package object math { - /** The `double` value that is closer than any other to `e`, the base of + /** The `Double` value that is closer than any other to `e`, the base of * the natural logarithms. + * @group math-const */ @inline final val E = java.lang.Math.E - /** The `double` value that is closer than any other to `pi`, the ratio of + /** The `Double` value that is closer than any other to `pi`, the ratio of * the circumference of a circle to its diameter. + * @group math-const */ @inline final val Pi = java.lang.Math.PI - /** Returns a `double` value with a positive sign, greater than or equal + /** Returns a `Double` value with a positive sign, greater than or equal * to `0.0` and less than `1.0`. + * + * @group randomisation */ def random(): Double = java.lang.Math.random() + /** @group trig */ def sin(x: Double): Double = java.lang.Math.sin(x) + /** @group trig */ def cos(x: Double): Double = java.lang.Math.cos(x) + /** @group trig */ def tan(x: Double): Double = java.lang.Math.tan(x) + /** @group trig */ def asin(x: Double): Double = java.lang.Math.asin(x) + /** @group trig */ def acos(x: Double): Double = java.lang.Math.acos(x) + /** @group trig */ def atan(x: Double): Double = java.lang.Math.atan(x) /** Converts an angle measured in degrees to an approximately equivalent @@ -40,6 +102,7 @@ package object math { * * @param x an angle, in degrees * @return the measurement of the angle `x` in radians. + * @group angle-conversion */ def toRadians(x: Double): Double = java.lang.Math.toRadians(x) @@ -48,44 +111,10 @@ package object math { * * @param x angle, in radians * @return the measurement of the angle `x` in degrees. + * @group angle-conversion */ def toDegrees(x: Double): Double = java.lang.Math.toDegrees(x) - /** Returns Euler's number `e` raised to the power of a `double` value. - * - * @param x the exponent to raise `e` to. - * @return the value `e^a^`, where `e` is the base of the natural - * logarithms. - */ - def exp(x: Double): Double = java.lang.Math.exp(x) - - /** Returns the natural logarithm of a `double` value. - * - * @param x the number to take the natural logarithm of - * @return the value `logₑ(x)` where `e` is Eulers number - */ - def log(x: Double): Double = java.lang.Math.log(x) - - /** Returns the square root of a `double` value. - * - * @param x the number to take the square root of - * @return the value √x - */ - def sqrt(x: Double): Double = java.lang.Math.sqrt(x) - def IEEEremainder(x: Double, y: Double): Double = java.lang.Math.IEEEremainder(x, y) - - def ceil(x: Double): Double = java.lang.Math.ceil(x) - def floor(x: Double): Double = java.lang.Math.floor(x) - - /** Returns the `double` value that is closest in value to the - * argument and is equal to a mathematical integer. - * - * @param x a `double` value - * @return the closest floating-point value to a that is equal to a - * mathematical integer. - */ - def rint(x: Double): Double = java.lang.Math.rint(x) - /** Converts rectangular coordinates `(x, y)` to polar `(r, theta)`. * * @param x the ordinate coordinate @@ -93,19 +122,44 @@ package object math { * @return the ''theta'' component of the point `(r, theta)` in polar * coordinates that corresponds to the point `(x, y)` in * Cartesian coordinates. + * @group polar-coords */ def atan2(y: Double, x: Double): Double = java.lang.Math.atan2(y, x) - /** Returns the value of the first argument raised to the power of the - * second argument. + /** Returns the square root of the sum of the squares of both given `Double` + * values without intermediate underflow or overflow. + * + * The ''r'' component of the point `(r, theta)` in polar + * coordinates that corresponds to the point `(x, y)` in + * Cartesian coordinates. + * @group polar-coords + */ + def hypot(x: Double, y: Double): Double = java.lang.Math.hypot(x, y) + + // ----------------------------------------------------------------------- + // rounding functions + // ----------------------------------------------------------------------- + + /** @group rounding */ + def ceil(x: Double): Double = java.lang.Math.ceil(x) + /** @group rounding */ + def floor(x: Double): Double = java.lang.Math.floor(x) + + /** Returns the `Double` value that is closest in value to the + * argument and is equal to a mathematical integer. + * + * @param x a `Double` value + * @return the closest floating-point value to a that is equal to a + * mathematical integer. + * @group rounding + */ + def rint(x: Double): Double = java.lang.Math.rint(x) + + /** There is no reason to round a `Long`, but this method prevents unintended conversion to `Float` followed by rounding to `Int`. * - * @param x the base. - * @param y the exponent. - * @return the value `x^y^`. + * @note Does not forward to [[java.lang.Math]] + * @group rounding */ - def pow(x: Double, y: Double): Double = java.lang.Math.pow(x, y) - - /** There is no reason to round a `Long`, but this method prevents unintended conversion to `Float` followed by rounding to `Int`. */ @deprecated("This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value?", "2.11.0") def round(x: Long): Long = x @@ -113,6 +167,7 @@ package object math { * * @param x a floating-point value to be rounded to a `Int`. * @return the value of the argument rounded to the nearest `Int` value. + * @group rounding */ def round(x: Float): Int = java.lang.Math.round(x) @@ -120,83 +175,153 @@ package object math { * * @param x a floating-point value to be rounded to a `Long`. * @return the value of the argument rounded to the nearest`long` value. + * @group rounding */ def round(x: Double): Long = java.lang.Math.round(x) + /** @group abs */ def abs(x: Int): Int = java.lang.Math.abs(x) + /** @group abs */ def abs(x: Long): Long = java.lang.Math.abs(x) + /** @group abs */ def abs(x: Float): Float = java.lang.Math.abs(x) + /** @group abs */ def abs(x: Double): Double = java.lang.Math.abs(x) + /** @group minmax */ def max(x: Int, y: Int): Int = java.lang.Math.max(x, y) + /** @group minmax */ def max(x: Long, y: Long): Long = java.lang.Math.max(x, y) + /** @group minmax */ def max(x: Float, y: Float): Float = java.lang.Math.max(x, y) + /** @group minmax */ def max(x: Double, y: Double): Double = java.lang.Math.max(x, y) + /** @group minmax */ def min(x: Int, y: Int): Int = java.lang.Math.min(x, y) + /** @group minmax */ def min(x: Long, y: Long): Long = java.lang.Math.min(x, y) + /** @group minmax */ def min(x: Float, y: Float): Float = java.lang.Math.min(x, y) + /** @group minmax */ def min(x: Double, y: Double): Double = java.lang.Math.min(x, y) - /** Note that these are not pure forwarders to the java versions. - * In particular, the return type of java.lang.Long.signum is Int, - * but here it is widened to Long so that each overloaded variant - * will return the same numeric type it is passed. - */ + /** @group signum + * @note Forwards to [[java.lang.Integer]] + */ def signum(x: Int): Int = java.lang.Integer.signum(x) + /** @group signum + * @note Forwards to [[java.lang.Long]] + */ def signum(x: Long): Long = java.lang.Long.signum(x) + /** @group signum */ def signum(x: Float): Float = java.lang.Math.signum(x) + /** @group signum */ def signum(x: Double): Double = java.lang.Math.signum(x) // ----------------------------------------------------------------------- // root functions // ----------------------------------------------------------------------- - /** Returns the cube root of the given `Double` value. */ + /** Returns the square root of a `Double` value. + * + * @param x the number to take the square root of + * @return the value √x + * @group root-extraction + */ + def sqrt(x: Double): Double = java.lang.Math.sqrt(x) + + /** Returns the cube root of the given `Double` value. + * + * @param x the number to take the cube root of + * @return the value ∛x + * @group root-extraction + */ def cbrt(x: Double): Double = java.lang.Math.cbrt(x) // ----------------------------------------------------------------------- // exponential functions // ----------------------------------------------------------------------- - /** Returns `exp(x) - 1`. */ + /** Returns the value of the first argument raised to the power of the + * second argument. + * + * @param x the base. + * @param y the exponent. + * @return the value `x^y^`. + * @group explog + */ + def pow(x: Double, y: Double): Double = java.lang.Math.pow(x, y) + + /** Returns Euler's number `e` raised to the power of a `Double` value. + * + * @param x the exponent to raise `e` to. + * @return the value `e^a^`, where `e` is the base of the natural + * logarithms. + * @group explog + */ + def exp(x: Double): Double = java.lang.Math.exp(x) + + /** Returns `exp(x) - 1`. + * @group explog + */ def expm1(x: Double): Double = java.lang.Math.expm1(x) // ----------------------------------------------------------------------- // logarithmic functions // ----------------------------------------------------------------------- - /** Returns the natural logarithm of the sum of the given `Double` value and 1. */ + /** Returns the natural logarithm of a `Double` value. + * + * @param x the number to take the natural logarithm of + * @return the value `logₑ(x)` where `e` is Eulers number + * @group explog + */ + def log(x: Double): Double = java.lang.Math.log(x) + + /** Returns the natural logarithm of the sum of the given `Double` value and 1. + * @group explog + */ def log1p(x: Double): Double = java.lang.Math.log1p(x) - /** Returns the base 10 logarithm of the given `Double` value. */ + /** Returns the base 10 logarithm of the given `Double` value. + * @group explog + */ def log10(x: Double): Double = java.lang.Math.log10(x) // ----------------------------------------------------------------------- // trigonometric functions // ----------------------------------------------------------------------- - /** Returns the hyperbolic sine of the given `Double` value. */ + /** Returns the hyperbolic sine of the given `Double` value. + * @group hyperbolic + */ def sinh(x: Double): Double = java.lang.Math.sinh(x) - /** Returns the hyperbolic cosine of the given `Double` value. */ + /** Returns the hyperbolic cosine of the given `Double` value. + * @group hyperbolic + */ def cosh(x: Double): Double = java.lang.Math.cosh(x) - /** Returns the hyperbolic tangent of the given `Double` value. */ + /** Returns the hyperbolic tangent of the given `Double` value. + * @group hyperbolic + */ def tanh(x: Double):Double = java.lang.Math.tanh(x) // ----------------------------------------------------------------------- // miscellaneous functions // ----------------------------------------------------------------------- - /** Returns the square root of the sum of the squares of both given `Double` - * values without intermediate underflow or overflow. + /** Returns the size of an ulp of the given `Double` value. + * @group ulp */ - def hypot(x: Double, y: Double): Double = java.lang.Math.hypot(x, y) - - /** Returns the size of an ulp of the given `Double` value. */ def ulp(x: Double): Double = java.lang.Math.ulp(x) - /** Returns the size of an ulp of the given `Float` value. */ + /** Returns the size of an ulp of the given `Float` value. + * @group ulp + */ def ulp(x: Float): Float = java.lang.Math.ulp(x) + + /** @group rounding */ + def IEEEremainder(x: Double, y: Double): Double = java.lang.Math.IEEEremainder(x, y) } From 78c3bfd2ec49a26604cc2eedb445555efaac14fe Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 6 Jul 2016 15:44:51 +0200 Subject: [PATCH 125/153] SI-8561 named subclasses for known Manifest / ClassTag instances This helps keeping ClassTag serialization stable under accidental changes (like changing the order of definitions, which would change the name of the anonymous classes). --- src/library/scala/reflect/ClassTag.scala | 4 +- src/library/scala/reflect/Manifest.scala | 113 +++++++++++++---------- test/files/run/t8549.scala | 37 +++----- 3 files changed, 84 insertions(+), 70 deletions(-) diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 1811d3a00fda..3a300e059316 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -134,6 +134,8 @@ object ClassTag { val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing val Null : ClassTag[scala.Null] = Manifest.Null + private class GenericClassTag[T](val runtimeClass: jClass[_]) extends ClassTag[T] + def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = runtimeClass1 match { case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]] @@ -148,7 +150,7 @@ object ClassTag { case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]] case NothingTYPE => ClassTag.Nothing.asInstanceOf[ClassTag[T]] case NullTYPE => ClassTag.Null.asInstanceOf[ClassTag[T]] - case _ => new ClassTag[T]{ def runtimeClass = runtimeClass1 } + case _ => new GenericClassTag[T](runtimeClass1) } def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass) diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index 369676c27398..9c38864194ee 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -9,7 +9,7 @@ package scala package reflect -import scala.collection.mutable.{ ArrayBuilder, WrappedArray } +import scala.collection.mutable.{ArrayBuilder, WrappedArray} /** A `Manifest[T]` is an opaque descriptor for type T. Its supported use * is to give access to the erasure of the type as a `Class` instance, as @@ -21,23 +21,22 @@ import scala.collection.mutable.{ ArrayBuilder, WrappedArray } * which are not yet adequately represented in manifests. * * Example usages: -{{{ - def arr[T] = new Array[T](0) // does not compile - def arr[T](implicit m: Manifest[T]) = new Array[T](0) // compiles - def arr[T: Manifest] = new Array[T](0) // shorthand for the preceding - - // Methods manifest, classManifest, and optManifest are in [[scala.Predef]]. - def isApproxSubType[T: Manifest, U: Manifest] = manifest[T] <:< manifest[U] - isApproxSubType[List[String], List[AnyRef]] // true - isApproxSubType[List[String], List[Int]] // false - - def methods[T: ClassManifest] = classManifest[T].erasure.getMethods - def retType[T: ClassManifest](name: String) = - methods[T] find (_.getName == name) map (_.getGenericReturnType) - - retType[Map[_, _]]("values") // Some(scala.collection.Iterable) -}}} + * {{{ + * def arr[T] = new Array[T](0) // does not compile + * def arr[T](implicit m: Manifest[T]) = new Array[T](0) // compiles + * def arr[T: Manifest] = new Array[T](0) // shorthand for the preceding * + * // Methods manifest, classManifest, and optManifest are in [[scala.Predef]]. + * def isApproxSubType[T: Manifest, U: Manifest] = manifest[T] <:< manifest[U] + * isApproxSubType[List[String], List[AnyRef]] // true + * isApproxSubType[List[String], List[Int]] // false + * + * def methods[T: ClassManifest] = classManifest[T].erasure.getMethods + * def retType[T: ClassManifest](name: String) = + * methods[T] find (_.getName == name) map (_.getGenericReturnType) + * + * retType[Map[_, _]]("values") // Some(scala.collection.Iterable) + * }}} */ @scala.annotation.implicitNotFound(msg = "No Manifest available for ${T}.") // TODO undeprecated until Scala reflection becomes non-experimental @@ -88,71 +87,79 @@ object ManifestFactory { def valueManifests: List[AnyValManifest[_]] = List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) - val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte]("Byte") { + private class ByteManifest extends AnyValManifest[scala.Byte]("Byte") { def runtimeClass = java.lang.Byte.TYPE override def newArray(len: Int): Array[Byte] = new Array[Byte](len) override def newWrappedArray(len: Int): WrappedArray[Byte] = new WrappedArray.ofByte(new Array[Byte](len)) override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte() private def readResolve(): Any = Manifest.Byte } + val Byte: AnyValManifest[Byte] = new ByteManifest - val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short]("Short") { + private class ShortManifest extends AnyValManifest[scala.Short]("Short") { def runtimeClass = java.lang.Short.TYPE override def newArray(len: Int): Array[Short] = new Array[Short](len) override def newWrappedArray(len: Int): WrappedArray[Short] = new WrappedArray.ofShort(new Array[Short](len)) override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort() private def readResolve(): Any = Manifest.Short } + val Short: AnyValManifest[Short] = new ShortManifest - val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char]("Char") { + private class CharManifest extends AnyValManifest[scala.Char]("Char") { def runtimeClass = java.lang.Character.TYPE override def newArray(len: Int): Array[Char] = new Array[Char](len) override def newWrappedArray(len: Int): WrappedArray[Char] = new WrappedArray.ofChar(new Array[Char](len)) override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar() private def readResolve(): Any = Manifest.Char } + val Char: AnyValManifest[Char] = new CharManifest - val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int]("Int") { + private class IntManifest extends AnyValManifest[scala.Int]("Int") { def runtimeClass = java.lang.Integer.TYPE override def newArray(len: Int): Array[Int] = new Array[Int](len) override def newWrappedArray(len: Int): WrappedArray[Int] = new WrappedArray.ofInt(new Array[Int](len)) override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt() private def readResolve(): Any = Manifest.Int } + val Int: AnyValManifest[Int] = new IntManifest - val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long]("Long") { + private class LongManifest extends AnyValManifest[scala.Long]("Long") { def runtimeClass = java.lang.Long.TYPE override def newArray(len: Int): Array[Long] = new Array[Long](len) override def newWrappedArray(len: Int): WrappedArray[Long] = new WrappedArray.ofLong(new Array[Long](len)) override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong() private def readResolve(): Any = Manifest.Long } + val Long: AnyValManifest[Long] = new LongManifest - val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float]("Float") { + private class FloatManifest extends AnyValManifest[scala.Float]("Float") { def runtimeClass = java.lang.Float.TYPE override def newArray(len: Int): Array[Float] = new Array[Float](len) override def newWrappedArray(len: Int): WrappedArray[Float] = new WrappedArray.ofFloat(new Array[Float](len)) override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat() private def readResolve(): Any = Manifest.Float } + val Float: AnyValManifest[Float] = new FloatManifest - val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double]("Double") { + private class DoubleManifest extends AnyValManifest[scala.Double]("Double") { def runtimeClass = java.lang.Double.TYPE override def newArray(len: Int): Array[Double] = new Array[Double](len) override def newWrappedArray(len: Int): WrappedArray[Double] = new WrappedArray.ofDouble(new Array[Double](len)) override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble() private def readResolve(): Any = Manifest.Double } + val Double: AnyValManifest[Double] = new DoubleManifest - val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean]("Boolean") { + private class BooleanManifest extends AnyValManifest[scala.Boolean]("Boolean") { def runtimeClass = java.lang.Boolean.TYPE override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) override def newWrappedArray(len: Int): WrappedArray[Boolean] = new WrappedArray.ofBoolean(new Array[Boolean](len)) override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean() private def readResolve(): Any = Manifest.Boolean } + val Boolean: AnyValManifest[Boolean] = new BooleanManifest - val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit]("Unit") { + private class UnitManifest extends AnyValManifest[scala.Unit]("Unit") { def runtimeClass = java.lang.Void.TYPE override def newArray(len: Int): Array[Unit] = new Array[Unit](len) override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len)) @@ -162,43 +169,49 @@ object ManifestFactory { else super.arrayClass(tp) private def readResolve(): Any = Manifest.Unit } + val Unit: AnyValManifest[Unit] = new UnitManifest private val ObjectTYPE = classOf[java.lang.Object] private val NothingTYPE = classOf[scala.runtime.Nothing$] private val NullTYPE = classOf[scala.runtime.Null$] - val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any](ObjectTYPE, "Any") { + private class AnyManifest extends PhantomManifest[scala.Any](ObjectTYPE, "Any") { override def newArray(len: Int) = new Array[scala.Any](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) private def readResolve(): Any = Manifest.Any } + val Any: Manifest[scala.Any] = new AnyManifest - val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object](ObjectTYPE, "Object") { + private class ObjectManifest extends PhantomManifest[java.lang.Object](ObjectTYPE, "Object") { override def newArray(len: Int) = new Array[java.lang.Object](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.Object } + val Object: Manifest[java.lang.Object] = new ObjectManifest val AnyRef: Manifest[scala.AnyRef] = Object.asInstanceOf[Manifest[scala.AnyRef]] - val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") { + private class AnyValPhantomManifest extends PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") { override def newArray(len: Int) = new Array[scala.AnyVal](len) override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.AnyVal } + val AnyVal: Manifest[scala.AnyVal] = new AnyValPhantomManifest - val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null](NullTYPE, "Null") { + private class NullManifest extends PhantomManifest[scala.Null](NullTYPE, "Null") { override def newArray(len: Int) = new Array[scala.Null](len) override def <:<(that: ClassManifest[_]): Boolean = (that ne null) && (that ne Nothing) && !(that <:< AnyVal) private def readResolve(): Any = Manifest.Null } + val Null: Manifest[scala.Null] = new NullManifest - val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") { + private class NothingManifest extends PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") { override def newArray(len: Int) = new Array[scala.Nothing](len) override def <:<(that: ClassManifest[_]): Boolean = (that ne null) private def readResolve(): Any = Manifest.Nothing } + val Nothing: Manifest[scala.Nothing] = new NothingManifest private class SingletonTypeManifest[T <: AnyRef](value: AnyRef) extends Manifest[T] { lazy val runtimeClass = value.getClass @@ -251,31 +264,37 @@ object ManifestFactory { def arrayType[T](arg: Manifest[_]): Manifest[Array[T]] = arg.asInstanceOf[Manifest[T]].arrayManifest + private class AbstractTypeManifest[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Seq[Manifest[_]]) extends Manifest[T] { + def runtimeClass = upperBound + override val typeArguments = args.toList + override def toString = prefix.toString+"#"+name+argString + } + /** Manifest for the abstract type `prefix # name`. `upperBound` is not * strictly necessary as it could be obtained by reflection. It was * added so that erasure can be calculated without reflection. */ def abstractType[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Manifest[_]*): Manifest[T] = - new Manifest[T] { - def runtimeClass = upperBound - override val typeArguments = args.toList - override def toString = prefix.toString+"#"+name+argString - } + new AbstractTypeManifest[T](prefix, name, upperBound, args) + + private class WildcardManifest[T](lowerBound: Manifest[_], upperBound: Manifest[_]) extends Manifest[T] { + def runtimeClass = upperBound.runtimeClass + override def toString = + "_" + + (if (lowerBound eq Nothing) "" else " >: "+lowerBound) + + (if (upperBound eq Nothing) "" else " <: "+upperBound) + } /** Manifest for the unknown type `_ >: L <: U` in an existential. */ def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] = - new Manifest[T] { - def runtimeClass = upperBound.runtimeClass - override def toString = - "_" + - (if (lowerBound eq Nothing) "" else " >: "+lowerBound) + - (if (upperBound eq Nothing) "" else " <: "+upperBound) - } + new WildcardManifest[T](lowerBound, upperBound) + + private class IntersectionTypeManifest[T](parents: Seq[Manifest[_]]) extends Manifest[T] { + def runtimeClass = parents.head.runtimeClass + override def toString = parents.mkString(" with ") + } /** Manifest for the intersection type `parents_0 with ... with parents_n`. */ def intersectionType[T](parents: Manifest[_]*): Manifest[T] = - new Manifest[T] { - def runtimeClass = parents.head.runtimeClass - override def toString = parents.mkString(" with ") - } + new IntersectionTypeManifest[T](parents) } diff --git a/test/files/run/t8549.scala b/test/files/run/t8549.scala index 1ce8933efb13..f8d6819e33b0 100644 --- a/test/files/run/t8549.scala +++ b/test/files/run/t8549.scala @@ -79,7 +79,7 @@ object Test extends App { } } - // Generated on 20160515-00:17:51 with Scala version 2.12.0-SNAPSHOT) + // Generated on 20160706-15:44:41 with Scala version 2.12.0-20160629-163201-6612ba0) overwrite.foreach(updateComment) check(Some(1))("rO0ABXNyAApzY2FsYS5Tb21lESLyaV6hi3QCAAFMAAF4dAASTGphdmEvbGFuZy9PYmplY3Q7eHIADHNjYWxhLk9wdGlvbv5pN/3bDmZ0AgAAeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAQ==") @@ -95,13 +95,10 @@ object Test extends App { import collection.{ mutable, immutable } class C - // TODO IMPLCLASS not stable across trait encoding change (removal of impl classes) - // java.io.InvalidClassException: scala.reflect.ClassTag$$anon$1; local class incompatible: stream classdesc serialVersionUID = -4937928798201944954, local class serialVersionUID = 4714485091895415501 - // Switch to using named, rather than anoymous classes, in the class tag implementation, or maybe use a `readResolve` / `writeReplace` approach. - // check(reflect.classTag[C])("rO0ABXNyAB5zY2FsYS5yZWZsZWN0LkNsYXNzVGFnJCRhbm9uJDG7ePPrmQBkhgIAAUwAD3J1bnRpbWVDbGFzczEkMXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHB2cgAGVGVzdCRDAAAAAAAAAAAAAAB4cA==") - // check(reflect.classTag[Int])("rO0ABXNyACVzY2FsYS5yZWZsZWN0Lk1hbmlmZXN0RmFjdG9yeSQkYW5vbiQ5zfmiSVNjtVICAAB4cgAcc2NhbGEucmVmbGVjdC5BbnlWYWxNYW5pZmVzdAAAAAAAAAABAgABTAAIdG9TdHJpbmd0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQAA0ludA==") - // check(reflect.classTag[String])("rO0ABXNyAB5zY2FsYS5yZWZsZWN0LkNsYXNzVGFnJCRhbm9uJDG7ePPrmQBkhgIAAUwAD3J1bnRpbWVDbGFzczEkMXQAEUxqYXZhL2xhbmcvQ2xhc3M7eHB2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHA=") - // check(reflect.classTag[Object])("rO0ABXNyACVzY2FsYS5yZWZsZWN0Lk1hbmlmZXN0RmFjdG9yeSQkYW5vbiQymPrtq/Ci1gsCAAB4cgAtc2NhbGEucmVmbGVjdC5NYW5pZmVzdEZhY3RvcnkkUGhhbnRvbU1hbmlmZXN0rzigP7KRh/kCAAFMAAh0b1N0cmluZ3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hyAC9zY2FsYS5yZWZsZWN0Lk1hbmlmZXN0RmFjdG9yeSRDbGFzc1R5cGVNYW5pZmVzdFq6NWvfTgYFAgADTAAGcHJlZml4dAAOTHNjYWxhL09wdGlvbjtMAAxydW50aW1lQ2xhc3N0ABFMamF2YS9sYW5nL0NsYXNzO0wADXR5cGVBcmd1bWVudHN0ACFMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvTGlzdDt4cHNyAAtzY2FsYS5Ob25lJEZQJPZTypSsAgAAeHIADHNjYWxhLk9wdGlvbv5pN/3bDmZ0AgAAeHB2cgAQamF2YS5sYW5nLk9iamVjdAAAAAAAAAAAAAAAeHBzcgAyc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTGlzdCRTZXJpYWxpemF0aW9uUHJveHkAAAAAAAAAAQMAAHhwc3IALHNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXJpYWxpemVFbmQkilxjW/dTC20CAAB4cHh0AAZPYmplY3Q=") + check(reflect.classTag[C])("rO0ABXNyACZzY2FsYS5yZWZsZWN0LkNsYXNzVGFnJEdlbmVyaWNDbGFzc1RhZy5VPJBpc7h/AgABTAAMcnVudGltZUNsYXNzdAARTGphdmEvbGFuZy9DbGFzczt4cHZyAAZUZXN0JEMAAAAAAAAAAAAAAHhw") + check(reflect.classTag[Int])("rO0ABXNyAClzY2FsYS5yZWZsZWN0Lk1hbmlmZXN0RmFjdG9yeSRJbnRNYW5pZmVzdFbjh2PQL01qAgAAeHIAHHNjYWxhLnJlZmxlY3QuQW55VmFsTWFuaWZlc3QAAAAAAAAAAQIAAUwACHRvU3RyaW5ndAASTGphdmEvbGFuZy9TdHJpbmc7eHB0AANJbnQ=") + check(reflect.classTag[String])("rO0ABXNyACZzY2FsYS5yZWZsZWN0LkNsYXNzVGFnJEdlbmVyaWNDbGFzc1RhZy5VPJBpc7h/AgABTAAMcnVudGltZUNsYXNzdAARTGphdmEvbGFuZy9DbGFzczt4cHZyABBqYXZhLmxhbmcuU3RyaW5noPCkOHo7s0ICAAB4cA==") + check(reflect.classTag[Object])("rO0ABXNyACxzY2FsYS5yZWZsZWN0Lk1hbmlmZXN0RmFjdG9yeSRPYmplY3RNYW5pZmVzdIWY9dplxtUqAgAAeHIALXNjYWxhLnJlZmxlY3QuTWFuaWZlc3RGYWN0b3J5JFBoYW50b21NYW5pZmVzdK84oD+ykYf5AgABTAAIdG9TdHJpbmd0ABJMamF2YS9sYW5nL1N0cmluZzt4cgAvc2NhbGEucmVmbGVjdC5NYW5pZmVzdEZhY3RvcnkkQ2xhc3NUeXBlTWFuaWZlc3TQb2e0Lu/6HQIAA0wABnByZWZpeHQADkxzY2FsYS9PcHRpb247TAAMcnVudGltZUNsYXNzdAARTGphdmEvbGFuZy9DbGFzcztMAA10eXBlQXJndW1lbnRzdAAhTHNjYWxhL2NvbGxlY3Rpb24vaW1tdXRhYmxlL0xpc3Q7eHBzcgALc2NhbGEuTm9uZSRGUCT2U8qUrAIAAHhyAAxzY2FsYS5PcHRpb27+aTf92w5mdAIAAHhwdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwc3IAMnNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3QkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAEDAAB4cHNyACxzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5MaXN0U2VyaWFsaXplRW5kJIpcY1v3UwttAgAAeHB4dAAGT2JqZWN0") // TODO SI-8576 unstable under -Xcheckinit // check(Enum)( "rO0ABXNyAApUZXN0JEVudW0ketCIyQ8C23MCAAJMAAJWMXQAGUxzY2FsYS9FbnVtZXJhdGlvbiRWYWx1ZTtMAAJWMnQAF0xzY2FsYS9FbnVtZXJhdGlvbiRWYWw7eHIAEXNjYWxhLkVudW1lcmF0aW9udaDN3ZgOWY4CAAhJAAZuZXh0SWRJABtzY2FsYSRFbnVtZXJhdGlvbiQkYm90dG9tSWRJABhzY2FsYSRFbnVtZXJhdGlvbiQkdG9wSWRMABRWYWx1ZU9yZGVyaW5nJG1vZHVsZXQAIkxzY2FsYS9FbnVtZXJhdGlvbiRWYWx1ZU9yZGVyaW5nJDtMAA9WYWx1ZVNldCRtb2R1bGV0AB1Mc2NhbGEvRW51bWVyYXRpb24kVmFsdWVTZXQkO0wACG5leHROYW1ldAAbTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmF0b3I7TAAXc2NhbGEkRW51bWVyYXRpb24kJG5tYXB0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDtMABdzY2FsYSRFbnVtZXJhdGlvbiQkdm1hcHEAfgAHeHAAAAArAAAAAAAAACtwcHBzcgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAAAAAAAAAAAQMAAHhwdw0AAALuAAAAAAAAAAQAeHNxAH4ACXcNAAAC7gAAAAEAAAAEAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAAqc3IAFXNjYWxhLkVudW1lcmF0aW9uJFZhbM9pZ6/J/O1PAgACSQAYc2NhbGEkRW51bWVyYXRpb24kVmFsJCRpTAAEbmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO3hyABdzY2FsYS5FbnVtZXJhdGlvbiRWYWx1ZWJpfC/tIR1RAgACTAAGJG91dGVydAATTHNjYWxhL0VudW1lcmF0aW9uO0wAHHNjYWxhJEVudW1lcmF0aW9uJCRvdXRlckVudW1xAH4AEnhwcQB+AAhxAH4ACAAAACpweHNyABFUZXN0JEVudW0kJGFub24kMVlIjlmE1sXaAgAAeHEAfgARcQB+AAhxAH4ACHEAfgAT") @@ -119,8 +116,7 @@ object Test extends App { // TODO SI-8576 unstable under -Xcheckinit check(collection.convert.Wrappers)( "rO0ABXNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkrrSziizavIECABJMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABJKTWFwV3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpNYXBXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwcA==") - // TODO IMPLCLASS java.io.InvalidClassException: scala.collection.immutable.Set$EmptySet$; local class incompatible: stream classdesc serialVersionUID = -1118802231467657162, local class serialVersionUID = -5214304379191661165 - // check(new collection.convert.Wrappers.SetWrapper(immutable.Set()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAABAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkrrSziizavIECABJMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABJKTWFwV3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpNYXBXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwcHNyAChzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TZXQkRW1wdHlTZXQk8Hk3TFN0uDYCAAB4cA==") + check(new collection.convert.Wrappers.SetWrapper(immutable.Set()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAABAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkrrSziizavIECABJMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABJKTWFwV3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpNYXBXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwcHNyAChzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TZXQkRW1wdHlTZXQkzP+rBndbbiMCAAB4cA==") check(new collection.convert.Wrappers.SetWrapper(immutable.Set(1, 2, 3)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAABAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkrrSziizavIECABJMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABJKTWFwV3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpNYXBXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwcHNyACNzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TZXQkU2V0M84syT0560SgAgADTAAFZWxlbTF0ABJMamF2YS9sYW5nL09iamVjdDtMAAVlbGVtMnEAfgAZTAAFZWxlbTNxAH4AGXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+ABsAAAACc3EAfgAbAAAAAw==") check(new collection.convert.Wrappers.SetWrapper(mutable.Set()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAABAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkrrSziizavIECABJMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABJKTWFwV3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpNYXBXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwcHNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaFNldAAAAAAAAAABAwAAeHB3DQAAAcIAAAAAAAAABQB4") check(new collection.convert.Wrappers.SetWrapper(mutable.Set(1, 2, 3)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAABAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkrrSziizavIECABJMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABJKTWFwV3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpNYXBXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwcHNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaFNldAAAAAAAAAABAwAAeHB3DQAAAcIAAAADAAAABQBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AGgAAAAJzcQB+ABoAAAADeA==") @@ -155,8 +151,7 @@ object Test extends App { // TODO SI-8576 throws scala.UnitializedFieldError under -Xcheckinit // check(new immutable.Range(0, 1, 1))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5SYW5nZWm7o1SrFTINAgAHSQADZW5kWgAHaXNFbXB0eUkAC2xhc3RFbGVtZW50SQAQbnVtUmFuZ2VFbGVtZW50c0kABXN0YXJ0SQAEc3RlcEkAD3Rlcm1pbmFsRWxlbWVudHhwAAAAAQAAAAAAAAAAAQAAAAAAAAABAAAAAQ==") - // TODO IMPLCLASS java.io.InvalidClassException: scala.collection.immutable.Set$EmptySet$; local class incompatible: stream classdesc serialVersionUID = -1118802231467657162, local class serialVersionUID = -5214304379191661165 - // check(immutable.Set())( "rO0ABXNyAChzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TZXQkRW1wdHlTZXQk8Hk3TFN0uDYCAAB4cA==") + check(immutable.Set())( "rO0ABXNyAChzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TZXQkRW1wdHlTZXQkzP+rBndbbiMCAAB4cA==") check(immutable.Set(1))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TZXQkU2V0MREd3c4yqtWTAgABTAAFZWxlbTF0ABJMamF2YS9sYW5nL09iamVjdDt4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAAB") check(immutable.Set(1, 2))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TZXQkU2V0MqaV02sZQzV0AgACTAAFZWxlbTF0ABJMamF2YS9sYW5nL09iamVjdDtMAAVlbGVtMnEAfgABeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAwAAAAI=") check(immutable.Set(1, 2, 3))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TZXQkU2V0M84syT0560SgAgADTAAFZWxlbTF0ABJMamF2YS9sYW5nL09iamVjdDtMAAVlbGVtMnEAfgABTAAFZWxlbTNxAH4AAXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAMAAAACc3EAfgADAAAAAw==") @@ -168,8 +163,7 @@ object Test extends App { // TODO SI-8576 Uninitialized field: IndexedSeqLike.scala: 56 // check(immutable.Stream(1, 2, 3))( "rO0ABXNyACZzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TdHJlYW0kQ29uc/ekjBXM3TlFAgADTAACaGR0ABJMamF2YS9sYW5nL09iamVjdDtMAAV0bEdlbnQAEUxzY2FsYS9GdW5jdGlvbjA7TAAFdGxWYWx0ACNMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvU3RyZWFtO3hyACFzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TdHJlYW0552RDntM42gIAAHhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcgAtc2NhbGEuY29sbGVjdGlvbi5JdGVyYXRvciQkYW5vbmZ1biR0b1N0cmVhbSQxRWR4We0SX0UCAAFMAAYkb3V0ZXJ0ABtMc2NhbGEvY29sbGVjdGlvbi9JdGVyYXRvcjt4cHNyAChzY2FsYS5jb2xsZWN0aW9uLkluZGV4ZWRTZXFMaWtlJEVsZW1lbnRzGF+1cBwmcx0CAANJAANlbmRJAAVpbmRleEwABiRvdXRlcnQAIUxzY2FsYS9jb2xsZWN0aW9uL0luZGV4ZWRTZXFMaWtlO3hwAAAAAwAAAAFzcgArc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLldyYXBwZWRBcnJheSRvZkludMmRLBcI15VjAgABWwAFYXJyYXl0AAJbSXhwdXIAAltJTbpgJnbqsqUCAAB4cAAAAAMAAAABAAAAAgAAAANw") - // TODO IMPLCLASS java.io.InvalidClassException: scala.math.Ordering$Int$; local class incompatible: stream classdesc serialVersionUID = 828746404302808924, local class serialVersionUID = -4070467079371527467 - // check(immutable.TreeSet[Int]())( "rO0ABXNyACJzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5UcmVlU2V0sRdVIDjbWAsCAAJMAAhvcmRlcmluZ3QAFUxzY2FsYS9tYXRoL09yZGVyaW5nO0wABHRyZWV0AC5Mc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQkC4BMdr1Z51wCAAB4cHA=") + check(immutable.TreeSet[Int]())( "rO0ABXNyACJzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5UcmVlU2V0sRdVIDjbWAsCAAJMAAhvcmRlcmluZ3QAFUxzY2FsYS9tYXRoL09yZGVyaW5nO0wABHRyZWV0AC5Mc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHA=") // TODO SI-8576 unstable under -Xcheckinit // check(immutable.TreeSet(1, 2, 3))( "rO0ABXNyACJzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5UcmVlU2V0sRdVIDjbWAsCAAJMAAhvcmRlcmluZ3QAFUxzY2FsYS9tYXRoL09yZGVyaW5nO0wABHRyZWV0AC5Mc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQkC4BMdr1Z51wCAAB4cHNyADFzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5SZWRCbGFja1RyZWUkQmxhY2tUcmVlzRxnCKenVAECAAB4cgAsc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWVrqCSyHJbsMgIABUkABWNvdW50TAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgACTAAFcmlnaHRxAH4AAkwABXZhbHVlcQB+AAh4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAnNxAH4ABgAAAAFzcQB+AAoAAAABcHBzcgAXc2NhbGEucnVudGltZS5Cb3hlZFVuaXR0pn1HHezLmgIAAHhwc3EAfgAGAAAAAXNxAH4ACgAAAANwcHEAfgAQcQB+ABA=") @@ -185,13 +179,12 @@ object Test extends App { check(mutable.HashMap())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcAAAAAAAAAABAwAAeHB3DQAAAu4AAAAAAAAABAB4") check(mutable.HashMap(1 -> 1))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcAAAAAAAAAABAwAAeHB3DQAAAu4AAAABAAAABABzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXEAfgAEeA==") check(mutable.HashSet(1, 2, 3))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaFNldAAAAAAAAAABAwAAeHB3DQAAAcIAAAADAAAABQBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAgAAAAJzcQB+AAIAAAADeA==") - // TODO IMPLCLASS java.io.InvalidClassException: scala.math.Ordering$Int$; local class incompatible: stream classdesc serialVersionUID = 828746404302808924, local class serialVersionUID = -4070467079371527467 - // check(mutable.TreeMap[Int, Int]())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcNx8qC229ZvwAgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZU1hcCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQkC4BMdr1Z51wCAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAABw") - // check(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcNx8qC229ZvwAgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZU1hcCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQkC4BMdr1Z51wCAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAAJzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSROb2RlGxHsFtValgACAAZaAANyZWRMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAARsZWZ0cQB+AAdMAAZwYXJlbnRxAH4AB0wABXJpZ2h0cQB+AAdMAAV2YWx1ZXEAfgAKeHAAc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFwcHNxAH4ACQFzcQB+AAwAAAADcHEAfgALcHNxAH4ADAAAAAZxAH4ADg==") - // check(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcCRUcmVlTWFwVmlldx7MCZxLhVQ8AgADTAAGJG91dGVydAAiTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9UcmVlTWFwO0wABGZyb210AA5Mc2NhbGEvT3B0aW9uO0wABXVudGlscQB+AAJ4cgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVNYXDcfKgttvWb8AIAAkwACG9yZGVyaW5ndAAVTHNjYWxhL21hdGgvT3JkZXJpbmc7TAAmc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJFRyZWVNYXAkJHRyZWV0ACxMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1JlZEJsYWNrVHJlZSRUcmVlO3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JAuATHa9WedcAgAAeHBzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSRUcmVlAEynNPA1phUCAAJJAARzaXplTAAEcm9vdHQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJE5vZGU7eHAAAAACc3IAKnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5SZWRCbGFja1RyZWUkTm9kZRsR7BbVWpYAAgAGWgADcmVkTAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgAKTAAGcGFyZW50cQB+AApMAAVyaWdodHEAfgAKTAAFdmFsdWVxAH4ADXhwAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcHBzcQB+AAwBc3EAfgAPAAAAA3BxAH4ADnBzcQB+AA8AAAAGcQB+ABFzcQB+AANxAH4ACHEAfgALc3IACnNjYWxhLlNvbWURIvJpXqGLdAIAAUwAAXhxAH4ADXhyAAxzY2FsYS5PcHRpb27+aTf92w5mdAIAAHhwcQB+ABFzcQB+ABZzcQB+AA8AAAAC") - // check(mutable.TreeSet[Int]())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldM10nxFQDpt4AgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZVNldCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQkC4BMdr1Z51wCAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAABw") - // check(mutable.TreeSet(1, 3))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldM10nxFQDpt4AgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZVNldCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQkC4BMdr1Z51wCAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAAJzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSROb2RlGxHsFtValgACAAZaAANyZWRMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAARsZWZ0cQB+AAdMAAZwYXJlbnRxAH4AB0wABXJpZ2h0cQB+AAdMAAV2YWx1ZXEAfgAKeHAAc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFwcHNxAH4ACQFzcQB+AAwAAAADcHEAfgALcHBw") - // check(mutable.TreeSet(1, 3).range(1, 2))( "rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldCRUcmVlU2V0Vmlld2JdAzqy0DpGAgADTAAGJG91dGVydAAiTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9UcmVlU2V0O0wABGZyb210AA5Mc2NhbGEvT3B0aW9uO0wABXVudGlscQB+AAJ4cgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXTNdJ8RUA6beAIAAkwACG9yZGVyaW5ndAAVTHNjYWxhL21hdGgvT3JkZXJpbmc7TAAmc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJFRyZWVTZXQkJHRyZWV0ACxMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1JlZEJsYWNrVHJlZSRUcmVlO3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JAuATHa9WedcAgAAeHBzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSRUcmVlAEynNPA1phUCAAJJAARzaXplTAAEcm9vdHQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJE5vZGU7eHAAAAACc3IAKnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5SZWRCbGFja1RyZWUkTm9kZRsR7BbVWpYAAgAGWgADcmVkTAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgAKTAAGcGFyZW50cQB+AApMAAVyaWdodHEAfgAKTAAFdmFsdWVxAH4ADXhwAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcHBzcQB+AAwBc3EAfgAPAAAAA3BxAH4ADnBwcHNxAH4AA3EAfgAIcQB+AAtzcgAKc2NhbGEuU29tZREi8mleoYt0AgABTAABeHEAfgANeHIADHNjYWxhLk9wdGlvbv5pN/3bDmZ0AgAAeHBxAH4AEXNxAH4AFXNxAH4ADwAAAAI=") + check(mutable.TreeMap[Int, Int]())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcNx8qC229ZvwAgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZU1hcCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAABw") + check(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcNx8qC229ZvwAgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZU1hcCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAAJzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSROb2RlGxHsFtValgACAAZaAANyZWRMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAARsZWZ0cQB+AAdMAAZwYXJlbnRxAH4AB0wABXJpZ2h0cQB+AAdMAAV2YWx1ZXEAfgAKeHAAc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFwcHNxAH4ACQFzcQB+AAwAAAADcHEAfgALcHNxAH4ADAAAAAZxAH4ADg==") + check(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcCRUcmVlTWFwVmlldx7MCZxLhVQ8AgADTAAGJG91dGVydAAiTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9UcmVlTWFwO0wABGZyb210AA5Mc2NhbGEvT3B0aW9uO0wABXVudGlscQB+AAJ4cgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVNYXDcfKgttvWb8AIAAkwACG9yZGVyaW5ndAAVTHNjYWxhL21hdGgvT3JkZXJpbmc7TAAmc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJFRyZWVNYXAkJHRyZWV0ACxMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1JlZEJsYWNrVHJlZSRUcmVlO3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JNmBnwaXZn6wAgAAeHBzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSRUcmVlAEynNPA1phUCAAJJAARzaXplTAAEcm9vdHQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJE5vZGU7eHAAAAACc3IAKnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5SZWRCbGFja1RyZWUkTm9kZRsR7BbVWpYAAgAGWgADcmVkTAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgAKTAAGcGFyZW50cQB+AApMAAVyaWdodHEAfgAKTAAFdmFsdWVxAH4ADXhwAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcHBzcQB+AAwBc3EAfgAPAAAAA3BxAH4ADnBzcQB+AA8AAAAGcQB+ABFzcQB+AANxAH4ACHEAfgALc3IACnNjYWxhLlNvbWURIvJpXqGLdAIAAUwAAXhxAH4ADXhyAAxzY2FsYS5PcHRpb27+aTf92w5mdAIAAHhwcQB+ABFzcQB+ABZzcQB+AA8AAAAC") + check(mutable.TreeSet[Int]())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldM10nxFQDpt4AgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZVNldCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAABw") + check(mutable.TreeSet(1, 3))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldM10nxFQDpt4AgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZVNldCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAAJzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSROb2RlGxHsFtValgACAAZaAANyZWRMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAARsZWZ0cQB+AAdMAAZwYXJlbnRxAH4AB0wABXJpZ2h0cQB+AAdMAAV2YWx1ZXEAfgAKeHAAc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFwcHNxAH4ACQFzcQB+AAwAAAADcHEAfgALcHBw") + check(mutable.TreeSet(1, 3).range(1, 2))( "rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldCRUcmVlU2V0Vmlld2JdAzqy0DpGAgADTAAGJG91dGVydAAiTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9UcmVlU2V0O0wABGZyb210AA5Mc2NhbGEvT3B0aW9uO0wABXVudGlscQB+AAJ4cgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXTNdJ8RUA6beAIAAkwACG9yZGVyaW5ndAAVTHNjYWxhL21hdGgvT3JkZXJpbmc7TAAmc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJFRyZWVTZXQkJHRyZWV0ACxMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1JlZEJsYWNrVHJlZSRUcmVlO3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JNmBnwaXZn6wAgAAeHBzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSRUcmVlAEynNPA1phUCAAJJAARzaXplTAAEcm9vdHQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJE5vZGU7eHAAAAACc3IAKnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5SZWRCbGFja1RyZWUkTm9kZRsR7BbVWpYAAgAGWgADcmVkTAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgAKTAAGcGFyZW50cQB+AApMAAVyaWdodHEAfgAKTAAFdmFsdWVxAH4ADXhwAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcHBzcQB+AAwBc3EAfgAPAAAAA3BxAH4ADnBwcHNxAH4AA3EAfgAIcQB+AAtzcgAKc2NhbGEuU29tZREi8mleoYt0AgABTAABeHEAfgANeHIADHNjYWxhLk9wdGlvbv5pN/3bDmZ0AgAAeHBxAH4AEXNxAH4AFXNxAH4ADwAAAAI=") // TODO SI-8576 Uninitialized field under -Xcheckinit // check(new mutable.History())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGlzdG9yeUhuXxDIFJrsAgACSQAKbWF4SGlzdG9yeUwAA2xvZ3QAIExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUXVldWU7eHAAAAPoc3IAHnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5RdWV1ZbjMURVfOuHHAgAAeHIAJHNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5NdXRhYmxlTGlzdFJpnjJ+gFbAAgADSQADbGVuTAAGZmlyc3QwdAAlTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9MaW5rZWRMaXN0O0wABWxhc3QwcQB+AAV4cAAAAABzcgAjc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZExpc3Sak+nGCZHaUQIAAkwABGVsZW10ABJMamF2YS9sYW5nL09iamVjdDtMAARuZXh0dAAeTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9TZXE7eHBwcQB+AApxAH4ACg==") check(mutable.LinkedHashMap(1 -> 2))( "rO0ABXNyACZzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuTGlua2VkSGFzaE1hcAAAAAAAAAABAwAAeHB3DQAAAu4AAAABAAAABABzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAgAAAAJ4") @@ -201,7 +194,7 @@ object Test extends App { // TODO SI-8576 unstable under -Xcheckinit // check(mutable.ListBuffer(1, 2, 3))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuTGlzdEJ1ZmZlci9y9I7QyWzGAwAEWgAIZXhwb3J0ZWRJAANsZW5MAAVsYXN0MHQAKUxzY2FsYS9jb2xsZWN0aW9uL2ltbXV0YWJsZS8kY29sb24kY29sb247TAAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJExpc3RCdWZmZXIkJHN0YXJ0dAAhTHNjYWxhL2NvbGxlY3Rpb24vaW1tdXRhYmxlL0xpc3Q7eHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ABAAAAAJzcQB+AAQAAAADc3IALHNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXJpYWxpemVFbmQkilxjW/dTC20CAAB4cHcFAAAAAAN4") check(new mutable.StringBuilder(new java.lang.StringBuilder("123")))( "rO0ABXNyACZzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuU3RyaW5nQnVpbGRlcomvqgGv1tTxAgABTAAKdW5kZXJseWluZ3QAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjt4cHNyABdqYXZhLmxhbmcuU3RyaW5nQnVpbGRlcjzV+xRaTGrLAwAAeHB3BAAAAAN1cgACW0OwJmaw4l2ErAIAAHhwAAAAEwAxADIAMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeA==") - check(mutable.UnrolledBuffer[Int]())( "rO0ABXNyACdzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVW5yb2xsZWRCdWZmZXIAAAAAAAAAAQMAAUwAA3RhZ3QAGExzY2FsYS9yZWZsZWN0L0NsYXNzVGFnO3hwc3IAJXNjYWxhLnJlZmxlY3QuTWFuaWZlc3RGYWN0b3J5JCRhbm9uJDnN+aJJU2O1UgIAAHhyABxzY2FsYS5yZWZsZWN0LkFueVZhbE1hbmlmZXN0AAAAAAAAAAECAAFMAAh0b1N0cmluZ3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwdAADSW50dwQAAAAAeA==") + check(mutable.UnrolledBuffer[Int]())( "rO0ABXNyACdzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVW5yb2xsZWRCdWZmZXIAAAAAAAAAAQMAAUwAA3RhZ3QAGExzY2FsYS9yZWZsZWN0L0NsYXNzVGFnO3hwc3IAKXNjYWxhLnJlZmxlY3QuTWFuaWZlc3RGYWN0b3J5JEludE1hbmlmZXN0VuOHY9AvTWoCAAB4cgAcc2NhbGEucmVmbGVjdC5BbnlWYWxNYW5pZmVzdAAAAAAAAAABAgABTAAIdG9TdHJpbmd0ABJMamF2YS9sYW5nL1N0cmluZzt4cHQAA0ludHcEAAAAAHg=") import collection.parallel check(parallel.immutable.ParHashMap(1 -> 2))( "rO0ABXNyAC5zY2FsYS5jb2xsZWN0aW9uLnBhcmFsbGVsLmltbXV0YWJsZS5QYXJIYXNoTWFwAAAAAAAAAAECAANMAA9TY2FuTGVhZiRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9wYXJhbGxlbC9QYXJJdGVyYWJsZUxpa2UkU2NhbkxlYWYkO0wAD1NjYW5Ob2RlJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL3BhcmFsbGVsL1Bhckl0ZXJhYmxlTGlrZSRTY2FuTm9kZSQ7TAAEdHJpZXQAJExzY2FsYS9jb2xsZWN0aW9uL2ltbXV0YWJsZS9IYXNoTWFwO3hwcHBzcgA1c2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCRTZXJpYWxpemF0aW9uUHJveHkAAAAAAAAAAgMAAHhwdwQAAAABc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAcAAAACeA==") From bd9654d4a22bcccbd98d0f33699ece25f2c0904a Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Thu, 7 Jul 2016 14:10:40 +0200 Subject: [PATCH 126/153] [squash] Fix bounds in contains --- src/library/scala/util/Either.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index 6da39692c51b..5c61d83a1a07 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -214,7 +214,7 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * @param elem the element to test. * @return `true` if the option has an element that is equal (as determined by `==`) to `elem`, `false` otherwise. */ - final def contains[AA >: A](elem: AA): Boolean = this match { + final def contains[BB >: B](elem: BB): Boolean = this match { case Right(b) => b == elem case Left(_) => false } From 7e933d5b5a4c1c8795b74e67e2148c6fc4ca19a6 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 6 Jul 2016 19:42:57 +0200 Subject: [PATCH 127/153] SI-6947 Better type parameter names for Map classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Type parameter names are currently assigned pretty much alphabetically without any meaning. This change renames all key parameters in Map classes from `A` to `K` and all value parameters from `B` to `V` to make them more meaningful. Derived names are renamed accordingly (e.g. `V1` instead of `B1` for an upper bound on `V`, `W` instead of `C` for a new value type). As a side-effect this solves the documentation problem in SI-6947. Due to using `B` both as a type parameter for `foldLeft[B]` in `GenTraversableOnce[A]` and in `Map[A, B]` which extends `GenTraversableOnce[(A, B)]`, the signature of `Map.foldLeft` was rendered in scaladoc as def foldLeft[B](z: B)(op: (B, (A, B)) ⇒ B): B Now you get an unambiguous version: def foldLeft[B](z: B)(op: (B, (K, V)) ⇒ B): B --- src/library/scala/collection/GenMap.scala | 14 +- src/library/scala/collection/GenMapLike.scala | 36 ++--- src/library/scala/collection/Map.scala | 24 +-- src/library/scala/collection/MapLike.scala | 142 +++++++++--------- .../scala/collection/immutable/Map.scala | 116 +++++++------- .../scala/collection/immutable/MapLike.scala | 55 ++++--- .../scala/collection/mutable/Map.scala | 40 ++--- .../scala/collection/mutable/MapLike.scala | 62 ++++---- test/files/run/xMigration.check | 6 +- 9 files changed, 247 insertions(+), 248 deletions(-) diff --git a/src/library/scala/collection/GenMap.scala b/src/library/scala/collection/GenMap.scala index d17a2de179e0..6bc507ae9319 100644 --- a/src/library/scala/collection/GenMap.scala +++ b/src/library/scala/collection/GenMap.scala @@ -18,18 +18,18 @@ import generic._ * @author Aleksandar Prokopec * @since 2.9 */ -trait GenMap[A, +B] -extends GenMapLike[A, B, GenMap[A, B]] - with GenIterable[(A, B)] +trait GenMap[K, +V] +extends GenMapLike[K, V, GenMap[K, V]] + with GenIterable[(K, V)] { - def seq: Map[A, B] + def seq: Map[K, V] - def updated [B1 >: B](key: A, value: B1): GenMap[A, B1] + def updated [V1 >: V](key: K, value: V1): GenMap[K, V1] } object GenMap extends GenMapFactory[GenMap] { - def empty[A, B]: immutable.Map[A, B] = immutable.Map.empty + def empty[K, V]: immutable.Map[K, V] = immutable.Map.empty /** $mapCanBuildFromInfo */ - implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B] + implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), GenMap[K, V]] = new MapCanBuildFrom[K, V] } diff --git a/src/library/scala/collection/GenMapLike.scala b/src/library/scala/collection/GenMapLike.scala index 2b39fa2289b8..f6c2d071b510 100644 --- a/src/library/scala/collection/GenMapLike.scala +++ b/src/library/scala/collection/GenMapLike.scala @@ -22,13 +22,13 @@ package collection * A map is a collection of bindings from keys to values, where there are * no duplicate keys. */ -trait GenMapLike[A, +B, +Repr] extends GenIterableLike[(A, B), Repr] with Equals with Parallelizable[(A, B), parallel.ParMap[A, B]] { - def default(key: A): B - def get(key: A): Option[B] - def apply(key: A): B - def seq: Map[A, B] - def +[B1 >: B](kv: (A, B1)): GenMap[A, B1] - def - (key: A): Repr +trait GenMapLike[K, +V, +Repr] extends GenIterableLike[(K, V), Repr] with Equals with Parallelizable[(K, V), parallel.ParMap[K, V]] { + def default(key: K): V + def get(key: K): Option[V] + def apply(key: K): V + def seq: Map[K, V] + def +[V1 >: V](kv: (K, V1)): GenMap[K, V1] + def - (key: K): Repr // This hash code must be symmetric in the contents but ought not // collide trivially. @@ -41,17 +41,17 @@ trait GenMapLike[A, +B, +Repr] extends GenIterableLike[(A, B), Repr] with Equals * @tparam B1 the result type of the default computation. * @return the value associated with `key` if it exists, * otherwise the result of the `default` computation. - * @usecase def getOrElse(key: A, default: => B): B + * @usecase def getOrElse(key: K, default: => V): V * @inheritdoc */ - def getOrElse[B1 >: B](key: A, default: => B1): B1 + def getOrElse[V1 >: V](key: K, default: => V1): V1 /** Tests whether this map contains a binding for a key. * * @param key the key * @return `true` if there is a binding for `key` in this map, `false` otherwise. */ - def contains(key: A): Boolean + def contains(key: K): Boolean /** Tests whether this map contains a binding for a key. This method, * which implements an abstract method of trait `PartialFunction`, @@ -60,47 +60,47 @@ trait GenMapLike[A, +B, +Repr] extends GenIterableLike[(A, B), Repr] with Equals * @param key the key * @return `true` if there is a binding for `key` in this map, `false` otherwise. */ - def isDefinedAt(key: A): Boolean + def isDefinedAt(key: K): Boolean - def keySet: GenSet[A] + def keySet: GenSet[K] /** Collects all keys of this map in an iterable collection. * * @return the keys of this map as an iterable. */ - def keys: GenIterable[A] + def keys: GenIterable[K] /** Collects all values of this map in an iterable collection. * * @return the values of this map as an iterable. */ - def values: GenIterable[B] + def values: GenIterable[V] /** Creates an iterator for all keys. * * @return an iterator over all keys. */ - def keysIterator: Iterator[A] + def keysIterator: Iterator[K] /** Creates an iterator for all values in this map. * * @return an iterator over all values that are associated with some key in this map. */ - def valuesIterator: Iterator[B] + def valuesIterator: Iterator[V] /** Filters this map by retaining only keys satisfying a predicate. * @param p the predicate used to test keys * @return an immutable map consisting only of those key value pairs of this map where the key satisfies * the predicate `p`. The resulting map wraps the original map without copying any elements. */ - def filterKeys(p: A => Boolean): GenMap[A, B] + def filterKeys(p: K => Boolean): GenMap[K, V] /** Transforms this map by applying a function to every retrieved value. * @param f the function used to transform values of this map. * @return a map view which maps every key of this map * to `f(this(key))`. The resulting map wraps the original map without copying any elements. */ - def mapValues[C](f: B => C): GenMap[A, C] + def mapValues[W](f: V => W): GenMap[K, W] /** Compares two maps structurally; i.e., checks if all mappings * contained in this map are also contained in the other map, diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala index 1e40fd8c245f..c9a943f1f724 100644 --- a/src/library/scala/collection/Map.scala +++ b/src/library/scala/collection/Map.scala @@ -12,7 +12,7 @@ package collection import generic._ /** - * A map from keys of type `A` to values of type `B`. + * A map from keys of type `K` to values of type `V`. * * $mapNote * @@ -22,15 +22,15 @@ import generic._ * '''Note:''' If your additions and mutations return the same kind of map as the map * you are defining, you should inherit from `MapLike` as well. * - * @tparam A the type of the keys in this map. - * @tparam B the type of the values associated with keys. + * @tparam K the type of the keys in this map. + * @tparam V the type of the values associated with keys. * * @since 1.0 */ -trait Map[A, +B] extends Iterable[(A, B)] with GenMap[A, B] with MapLike[A, B, Map[A, B]] { - def empty: Map[A, B] = Map.empty +trait Map[K, +V] extends Iterable[(K, V)] with GenMap[K, V] with MapLike[K, V, Map[K, V]] { + def empty: Map[K, V] = Map.empty - override def seq: Map[A, B] = this + override def seq: Map[K, V] = this } /** $factoryInfo @@ -38,22 +38,22 @@ trait Map[A, +B] extends Iterable[(A, B)] with GenMap[A, B] with MapLike[A, B, M * @define coll map */ object Map extends MapFactory[Map] { - def empty[A, B]: immutable.Map[A, B] = immutable.Map.empty + def empty[K, V]: immutable.Map[K, V] = immutable.Map.empty /** $mapCanBuildFromInfo */ - implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Map[A, B]] = new MapCanBuildFrom[A, B] + implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V] /** An abstract shell used by { mutable, immutable }.Map but not by collection.Map * because of variance issues. */ - abstract class WithDefault[A, +B](underlying: Map[A, B], d: A => B) extends AbstractMap[A, B] with Map[A, B] with Serializable { + abstract class WithDefault[K, +V](underlying: Map[K, V], d: K => V) extends AbstractMap[K, V] with Map[K, V] with Serializable { override def size = underlying.size - def get(key: A) = underlying.get(key) // removed in 2.9: orElse Some(default(key)) + def get(key: K) = underlying.get(key) // removed in 2.9: orElse Some(default(key)) def iterator = underlying.iterator - override def default(key: A): B = d(key) + override def default(key: K): V = d(key) } } /** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */ -abstract class AbstractMap[A, +B] extends AbstractIterable[(A, B)] with Map[A, B] +abstract class AbstractMap[K, +V] extends AbstractIterable[(K, V)] with Map[K, V] diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala index d4d85c43ec66..a087cb0f4542 100644 --- a/src/library/scala/collection/MapLike.scala +++ b/src/library/scala/collection/MapLike.scala @@ -28,10 +28,10 @@ import parallel.ParMap * To implement a concrete map, you need to provide implementations of the * following methods: * {{{ - * def get(key: A): Option[B] - * def iterator: Iterator[(A, B)] - * def + [B1 >: B](kv: (A, B1)): This - * def -(key: A): This + * def get(key: K): Option[V] + * def iterator: Iterator[(K, V)] + * def + [V1 >: V](kv: (K, V1)): This + * def -(key: K): This * }}} * If you wish that methods like `take`, `drop`, `filter` also return the same kind of map * you should also override: @@ -42,8 +42,8 @@ import parallel.ParMap * `size` for efficiency. * * @define mapTags - * @tparam A the type of the keys. - * @tparam B the type of associated values. + * @tparam K the type of the keys. + * @tparam V the type of associated values. * @tparam This the type of the map itself. * * @author Martin Odersky @@ -54,12 +54,12 @@ import parallel.ParMap * @define willNotTerminateInf * @define mayNotTerminateInf */ -trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] - extends PartialFunction[A, B] - with IterableLike[(A, B), This] - with GenMapLike[A, B, This] - with Subtractable[A, This] - with Parallelizable[(A, B), ParMap[A, B]] +trait MapLike[K, +V, +This <: MapLike[K, V, This] with Map[K, V]] + extends PartialFunction[K, V] + with IterableLike[(K, V), This] + with GenMapLike[K, V, This] + with Subtractable[K, This] + with Parallelizable[(K, V), ParMap[K, V]] { self => @@ -71,7 +71,7 @@ self => /** A common implementation of `newBuilder` for all maps in terms of `empty`. * Overridden for mutable maps in `mutable.MapLike`. */ - override protected[this] def newBuilder: Builder[(A, B), This] = new MapBuilder[A, B, This](empty) + override protected[this] def newBuilder: Builder[(K, V), This] = new MapBuilder[K, V, This](empty) /** Optionally returns the value associated with a key. * @@ -79,32 +79,32 @@ self => * @return an option value containing the value associated with `key` in this map, * or `None` if none exists. */ - def get(key: A): Option[B] + def get(key: K): Option[V] /** Creates a new iterator over all key/value pairs of this map * * @return the new iterator */ - def iterator: Iterator[(A, B)] + def iterator: Iterator[(K, V)] /** Adds a key/value pair to this map, returning a new map. * @param kv the key/value pair - * @tparam B1 the type of the value in the key/value pair. + * @tparam V1 the type of the value in the key/value pair. * @return a new map with the new binding added to this map * - * @usecase def + (kv: (A, B)): Map[A, B] + * @usecase def + (kv: (K, V)): Map[K, V] * @inheritdoc */ - def + [B1 >: B] (kv: (A, B1)): Map[A, B1] + def + [V1 >: V] (kv: (K, V1)): Map[K, V1] /** Removes a key from this map, returning a new map. * @param key the key to be removed * @return a new map without a binding for `key` * - * @usecase def - (key: A): Map[A, B] + * @usecase def - (key: K): Map[K, V] * @inheritdoc */ - def - (key: A): This + def - (key: K): This /** Tests whether the map is empty. * @@ -116,14 +116,14 @@ self => * @param key the key. * @param default a computation that yields a default value in case no binding for `key` is * found in the map. - * @tparam B1 the result type of the default computation. + * @tparam V1 the result type of the default computation. * @return the value associated with `key` if it exists, * otherwise the result of the `default` computation. * - * @usecase def getOrElse(key: A, default: => B): B + * @usecase def getOrElse(key: K, default: => V): V * @inheritdoc */ - def getOrElse[B1 >: B](key: A, default: => B1): B1 = get(key) match { + def getOrElse[V1 >: V](key: K, default: => V1): V1 = get(key) match { case Some(v) => v case None => default } @@ -137,7 +137,7 @@ self => * @return the value associated with the given key, or the result of the * map's `default` method, if none exists. */ - def apply(key: A): B = get(key) match { + def apply(key: K): V = get(key) match { case None => default(key) case Some(value) => value } @@ -147,7 +147,7 @@ self => * @param key the key * @return `true` if there is a binding for `key` in this map, `false` otherwise. */ - def contains(key: A): Boolean = get(key).isDefined + def contains(key: K): Boolean = get(key).isDefined /** Tests whether this map contains a binding for a key. This method, * which implements an abstract method of trait `PartialFunction`, @@ -156,33 +156,33 @@ self => * @param key the key * @return `true` if there is a binding for `key` in this map, `false` otherwise. */ - def isDefinedAt(key: A) = contains(key) + def isDefinedAt(key: K) = contains(key) override /*PartialFunction*/ - def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = + def applyOrElse[K1 <: K, V1 >: V](x: K1, default: K1 => V1): V1 = getOrElse(x, default(x)) /** Collects all keys of this map in a set. * @return a set containing all keys of this map. */ - def keySet: Set[A] = new DefaultKeySet + def keySet: Set[K] = new DefaultKeySet /** The implementation class of the set returned by `keySet`. */ - protected class DefaultKeySet extends AbstractSet[A] with Set[A] with Serializable { - def contains(key : A) = self.contains(key) + protected class DefaultKeySet extends AbstractSet[K] with Set[K] with Serializable { + def contains(key : K) = self.contains(key) def iterator = keysIterator - def + (elem: A): Set[A] = (Set[A]() ++ this + elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem - def - (elem: A): Set[A] = (Set[A]() ++ this - elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem + def + (elem: K): Set[K] = (Set[K]() ++ this + elem).asInstanceOf[Set[K]] // !!! concrete overrides abstract problem + def - (elem: K): Set[K] = (Set[K]() ++ this - elem).asInstanceOf[Set[K]] // !!! concrete overrides abstract problem override def size = self.size - override def foreach[U](f: A => U) = self.keysIterator foreach f + override def foreach[U](f: K => U) = self.keysIterator foreach f } /** Creates an iterator for all keys. * * @return an iterator over all keys. */ - def keysIterator: Iterator[A] = new AbstractIterator[A] { + def keysIterator: Iterator[K] = new AbstractIterator[K] { val iter = self.iterator def hasNext = iter.hasNext def next() = iter.next()._1 @@ -192,29 +192,29 @@ self => * * @return the keys of this map as an iterable. */ - @migration("`keys` returns `Iterable[A]` rather than `Iterator[A]`.", "2.8.0") - def keys: Iterable[A] = keySet + @migration("`keys` returns `Iterable[K]` rather than `Iterator[K]`.", "2.8.0") + def keys: Iterable[K] = keySet /** Collects all values of this map in an iterable collection. * * @return the values of this map as an iterable. */ - @migration("`values` returns `Iterable[B]` rather than `Iterator[B]`.", "2.8.0") - def values: Iterable[B] = new DefaultValuesIterable + @migration("`values` returns `Iterable[V]` rather than `Iterator[V]`.", "2.8.0") + def values: Iterable[V] = new DefaultValuesIterable /** The implementation class of the iterable returned by `values`. */ - protected class DefaultValuesIterable extends AbstractIterable[B] with Iterable[B] with Serializable { + protected class DefaultValuesIterable extends AbstractIterable[V] with Iterable[V] with Serializable { def iterator = valuesIterator override def size = self.size - override def foreach[U](f: B => U) = self.valuesIterator foreach f + override def foreach[U](f: V => U) = self.valuesIterator foreach f } /** Creates an iterator for all values in this map. * * @return an iterator over all values that are associated with some key in this map. */ - def valuesIterator: Iterator[B] = new AbstractIterator[B] { + def valuesIterator: Iterator[V] = new AbstractIterator[V] { val iter = self.iterator def hasNext = iter.hasNext def next() = iter.next()._2 @@ -228,33 +228,33 @@ self => * @param key the given key value for which a binding is missing. * @throws NoSuchElementException */ - def default(key: A): B = + def default(key: K): V = throw new NoSuchElementException("key not found: " + key) - protected class FilteredKeys(p: A => Boolean) extends AbstractMap[A, B] with DefaultMap[A, B] { - override def foreach[U](f: ((A, B)) => U): Unit = for (kv <- self) if (p(kv._1)) f(kv) + protected class FilteredKeys(p: K => Boolean) extends AbstractMap[K, V] with DefaultMap[K, V] { + override def foreach[U](f: ((K, V)) => U): Unit = for (kv <- self) if (p(kv._1)) f(kv) def iterator = self.iterator.filter(kv => p(kv._1)) - override def contains(key: A) = p(key) && self.contains(key) - def get(key: A) = if (!p(key)) None else self.get(key) + override def contains(key: K) = p(key) && self.contains(key) + def get(key: K) = if (!p(key)) None else self.get(key) } /** Filters this map by retaining only keys satisfying a predicate. * - * '''Note''': the predicate must accept any key of type `A`, not just those already + * '''Note''': the predicate must accept any key of type `K`, not just those already * present in the map, as the predicate is tested before the underlying map is queried. * * @param p the predicate used to test keys * @return an immutable map consisting only of those key value pairs of this map where the key satisfies * the predicate `p`. The resulting map wraps the original map without copying any elements. */ - def filterKeys(p: A => Boolean): Map[A, B] = new FilteredKeys(p) + def filterKeys(p: K => Boolean): Map[K, V] = new FilteredKeys(p) - protected class MappedValues[C](f: B => C) extends AbstractMap[A, C] with DefaultMap[A, C] { - override def foreach[U](g: ((A, C)) => U): Unit = for ((k, v) <- self) g((k, f(v))) + protected class MappedValues[W](f: V => W) extends AbstractMap[K, W] with DefaultMap[K, W] { + override def foreach[U](g: ((K, W)) => U): Unit = for ((k, v) <- self) g((k, f(v))) def iterator = for ((k, v) <- self.iterator) yield (k, f(v)) override def size = self.size - override def contains(key: A) = self.contains(key) - def get(key: A) = self.get(key).map(f) + override def contains(key: K) = self.contains(key) + def get(key: K) = self.get(key).map(f) } /** Transforms this map by applying a function to every retrieved value. @@ -262,22 +262,22 @@ self => * @return a map view which maps every key of this map * to `f(this(key))`. The resulting map wraps the original map without copying any elements. */ - def mapValues[C](f: B => C): Map[A, C] = new MappedValues(f) + def mapValues[W](f: V => W): Map[K, W] = new MappedValues(f) // The following 5 operations (updated, two times +, two times ++) should really be - // generic, returning This[B]. We need better covariance support to express that though. + // generic, returning This[V]. We need better covariance support to express that though. // So right now we do the brute force approach of code duplication. /** Creates a new map obtained by updating this map with a given key/value pair. * @param key the key * @param value the value - * @tparam B1 the type of the added value + * @tparam V1 the type of the added value * @return A new map with the new key/value mapping added to this map. * - * @usecase def updated(key: A, value: B): Map[A, B] + * @usecase def updated(key: K, value: V): Map[K, V] * @inheritdoc */ - def updated [B1 >: B](key: A, value: B1): Map[A, B1] = this + ((key, value)) + def updated [V1 >: V](key: K, value: V1): Map[K, V1] = this + ((key, value)) /** Adds key/value pairs to this map, returning a new map. * @@ -287,27 +287,27 @@ self => * @param kv1 the first key/value pair * @param kv2 the second key/value pair * @param kvs the remaining key/value pairs - * @tparam B1 the type of the added values + * @tparam V1 the type of the added values * @return a new map with the given bindings added to this map * - * @usecase def + (kvs: (A, B)*): Map[A, B] + * @usecase def + (kvs: (K, V)*): Map[K, V] * @inheritdoc * @param kvs the key/value pairs */ - def + [B1 >: B] (kv1: (A, B1), kv2: (A, B1), kvs: (A, B1) *): Map[A, B1] = + def + [V1 >: V] (kv1: (K, V1), kv2: (K, V1), kvs: (K, V1) *): Map[K, V1] = this + kv1 + kv2 ++ kvs /** Adds all key/value pairs in a traversable collection to this map, returning a new map. * * @param xs the collection containing the added key/value pairs - * @tparam B1 the type of the added values + * @tparam V1 the type of the added values * @return a new map with the given bindings added to this map * - * @usecase def ++ (xs: Traversable[(A, B)]): Map[A, B] + * @usecase def ++ (xs: Traversable[(K, V)]): Map[K, V] * @inheritdoc */ - def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1] = - ((repr: Map[A, B1]) /: xs.seq) (_ + _) + def ++[V1 >: V](xs: GenTraversableOnce[(K, V1)]): Map[K, V1] = + ((repr: Map[K, V1]) /: xs.seq) (_ + _) /** Returns a new map obtained by removing all key/value pairs for which the predicate * `p` returns `true`. @@ -320,31 +320,31 @@ self => * @param p A predicate over key-value pairs * @return A new map containing elements not satisfying the predicate. */ - override def filterNot(p: ((A, B)) => Boolean): This = { + override def filterNot(p: ((K, V)) => Boolean): This = { var res: This = repr for (kv <- this) if (p(kv)) res = (res - kv._1).asInstanceOf[This] // !!! concrete overrides abstract problem res } - override def toSeq: Seq[(A, B)] = { - if (isEmpty) Vector.empty[(A, B)] + override def toSeq: Seq[(K, V)] = { + if (isEmpty) Vector.empty[(K, V)] else { // Default appropriate for immutable collections; mutable collections override this - val vb = Vector.newBuilder[(A, B)] + val vb = Vector.newBuilder[(K, V)] foreach(vb += _) vb.result } } - override def toBuffer[C >: (A, B)]: mutable.Buffer[C] = { - val result = new mutable.ArrayBuffer[C](size) + override def toBuffer[E >: (K, V)]: mutable.Buffer[E] = { + val result = new mutable.ArrayBuffer[E](size) // Faster to let the map iterate itself than to defer through copyToBuffer foreach(result += _) result } - protected[this] override def parCombiner = ParMap.newCombiner[A, B] + protected[this] override def parCombiner = ParMap.newCombiner[K, V] /** Appends all bindings of this map to a string builder using start, end, and separator strings. * The written text begins with the string `start` and ends with the string diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index 6f135cd35f4a..cbdf7b39f5a1 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -18,30 +18,30 @@ import generic._ * functionality for the abstract methods in `Map`: * * {{{ - * def get(key: A): Option[B] - * def iterator: Iterator[(A, B)] - * def + [B1 >: B](kv: (A, B1)): Map[A, B1] - * def -(key: A): Map[A, B] + * def get(key: K): Option[V] + * def iterator: Iterator[(K, V)] + * def + [V1 >: V](kv: (K, V1)): Map[K, V1] + * def -(key: K): Map[K, V] * }}} * * @since 1 */ -trait Map[A, +B] extends Iterable[(A, B)] -// with GenMap[A, B] - with scala.collection.Map[A, B] - with MapLike[A, B, Map[A, B]] { self => +trait Map[K, +V] extends Iterable[(K, V)] +// with GenMap[K, V] + with scala.collection.Map[K, V] + with MapLike[K, V, Map[K, V]] { self => - override def empty: Map[A, B] = Map.empty + override def empty: Map[K, V] = Map.empty /** Returns this $coll as an immutable map. * * A new map will not be built; lazy collections will stay lazy. */ @deprecatedOverriding("Immutable maps should do nothing on toMap except return themselves cast as a map.", "2.11.0") - override def toMap[T, U](implicit ev: (A, B) <:< (T, U)): immutable.Map[T, U] = + override def toMap[T, U](implicit ev: (K, V) <:< (T, U)): immutable.Map[T, U] = self.asInstanceOf[immutable.Map[T, U]] - override def seq: Map[A, B] = this + override def seq: Map[K, V] = this /** The same map with a given default function. * Note: `get`, `contains`, `iterator`, `keys`, etc are not affected by `withDefault`. @@ -51,7 +51,7 @@ trait Map[A, +B] extends Iterable[(A, B)] * @param d the function mapping keys to values, used for non-present keys * @return a wrapper of the map with a default value */ - def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1] = new Map.WithDefault[A, B1](this, d) + def withDefault[V1 >: V](d: K => V1): immutable.Map[K, V1] = new Map.WithDefault[K, V1](this, d) /** The same map with a given default value. * Note: `get`, `contains`, `iterator`, `keys`, etc are not affected by `withDefaultValue`. @@ -61,15 +61,15 @@ trait Map[A, +B] extends Iterable[(A, B)] * @param d default value used for non-present keys * @return a wrapper of the map with a default value */ - def withDefaultValue[B1 >: B](d: B1): immutable.Map[A, B1] = new Map.WithDefault[A, B1](this, x => d) + def withDefaultValue[V1 >: V](d: V1): immutable.Map[K, V1] = new Map.WithDefault[K, V1](this, x => d) /** Add a key/value pair to this map. * @param key the key * @param value the value * @return A new map with the new binding added to this map */ - override def updated [B1 >: B](key: A, value: B1): Map[A, B1] - def + [B1 >: B](kv: (A, B1)): Map[A, B1] + override def updated [V1 >: V](key: K, value: V1): Map[K, V1] + def + [V1 >: V](kv: (K, V1)): Map[K, V1] } /** $factoryInfo @@ -79,17 +79,17 @@ trait Map[A, +B] extends Iterable[(A, B)] object Map extends ImmutableMapFactory[Map] { /** $mapCanBuildFromInfo */ - implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Map[A, B]] = new MapCanBuildFrom[A, B] + implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V] - def empty[A, B]: Map[A, B] = EmptyMap.asInstanceOf[Map[A, B]] + def empty[K, V]: Map[K, V] = EmptyMap.asInstanceOf[Map[K, V]] - class WithDefault[A, +B](underlying: Map[A, B], d: A => B) extends scala.collection.Map.WithDefault[A, B](underlying, d) with Map[A, B] { + class WithDefault[K, +V](underlying: Map[K, V], d: K => V) extends scala.collection.Map.WithDefault[K, V](underlying, d) with Map[K, V] { override def empty = new WithDefault(underlying.empty, d) - override def updated[B1 >: B](key: A, value: B1): WithDefault[A, B1] = new WithDefault[A, B1](underlying.updated[B1](key, value), d) - override def + [B1 >: B](kv: (A, B1)): WithDefault[A, B1] = updated(kv._1, kv._2) - override def - (key: A): WithDefault[A, B] = new WithDefault(underlying - key, d) - override def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1] = new WithDefault[A, B1](underlying, d) - override def withDefaultValue[B1 >: B](d: B1): immutable.Map[A, B1] = new WithDefault[A, B1](underlying, x => d) + override def updated[V1 >: V](key: K, value: V1): WithDefault[K, V1] = new WithDefault[K, V1](underlying.updated[V1](key, value), d) + override def + [V1 >: V](kv: (K, V1)): WithDefault[K, V1] = updated(kv._1, kv._2) + override def - (key: K): WithDefault[K, V] = new WithDefault(underlying - key, d) + override def withDefault[V1 >: V](d: K => V1): immutable.Map[K, V1] = new WithDefault[K, V1](underlying, d) + override def withDefaultValue[V1 >: V](d: V1): immutable.Map[K, V1] = new WithDefault[K, V1](underlying, x => d) } private object EmptyMap extends AbstractMap[Any, Nothing] with Map[Any, Nothing] with Serializable { @@ -98,119 +98,119 @@ object Map extends ImmutableMapFactory[Map] { override def contains(key: Any) = false def get(key: Any): Option[Nothing] = None def iterator: Iterator[(Any, Nothing)] = Iterator.empty - override def updated [B1] (key: Any, value: B1): Map[Any, B1] = new Map1(key, value) - def + [B1](kv: (Any, B1)): Map[Any, B1] = updated(kv._1, kv._2) + override def updated [V1] (key: Any, value: V1): Map[Any, V1] = new Map1(key, value) + def + [V1](kv: (Any, V1)): Map[Any, V1] = updated(kv._1, kv._2) def - (key: Any): Map[Any, Nothing] = this } - class Map1[A, +B](key1: A, value1: B) extends AbstractMap[A, B] with Map[A, B] with Serializable { + class Map1[K, +V](key1: K, value1: V) extends AbstractMap[K, V] with Map[K, V] with Serializable { override def size = 1 - override def apply(key: A) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key) - override def contains(key: A) = key == key1 - def get(key: A): Option[B] = + override def apply(key: K) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key) + override def contains(key: K) = key == key1 + def get(key: K): Option[V] = if (key == key1) Some(value1) else None def iterator = Iterator((key1, value1)) - override def updated [B1 >: B] (key: A, value: B1): Map[A, B1] = + override def updated [V1 >: V] (key: K, value: V1): Map[K, V1] = if (key == key1) new Map1(key1, value) else new Map2(key1, value1, key, value) - def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2) - def - (key: A): Map[A, B] = + def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2) + def - (key: K): Map[K, V] = if (key == key1) Map.empty else this - override def foreach[U](f: ((A, B)) => U): Unit = { + override def foreach[U](f: ((K, V)) => U): Unit = { f((key1, value1)) } } - class Map2[A, +B](key1: A, value1: B, key2: A, value2: B) extends AbstractMap[A, B] with Map[A, B] with Serializable { + class Map2[K, +V](key1: K, value1: V, key2: K, value2: V) extends AbstractMap[K, V] with Map[K, V] with Serializable { override def size = 2 - override def apply(key: A) = + override def apply(key: K) = if (key == key1) value1 else if (key == key2) value2 else throw new NoSuchElementException("key not found: " + key) - override def contains(key: A) = (key == key1) || (key == key2) - def get(key: A): Option[B] = + override def contains(key: K) = (key == key1) || (key == key2) + def get(key: K): Option[V] = if (key == key1) Some(value1) else if (key == key2) Some(value2) else None def iterator = Iterator((key1, value1), (key2, value2)) - override def updated [B1 >: B] (key: A, value: B1): Map[A, B1] = + override def updated [V1 >: V] (key: K, value: V1): Map[K, V1] = if (key == key1) new Map2(key1, value, key2, value2) else if (key == key2) new Map2(key1, value1, key2, value) else new Map3(key1, value1, key2, value2, key, value) - def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2) - def - (key: A): Map[A, B] = + def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2) + def - (key: K): Map[K, V] = if (key == key1) new Map1(key2, value2) else if (key == key2) new Map1(key1, value1) else this - override def foreach[U](f: ((A, B)) => U): Unit = { + override def foreach[U](f: ((K, V)) => U): Unit = { f((key1, value1)); f((key2, value2)) } } - class Map3[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B) extends AbstractMap[A, B] with Map[A, B] with Serializable { + class Map3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends AbstractMap[K, V] with Map[K, V] with Serializable { override def size = 3 - override def apply(key: A) = + override def apply(key: K) = if (key == key1) value1 else if (key == key2) value2 else if (key == key3) value3 else throw new NoSuchElementException("key not found: " + key) - override def contains(key: A) = (key == key1) || (key == key2) || (key == key3) - def get(key: A): Option[B] = + override def contains(key: K) = (key == key1) || (key == key2) || (key == key3) + def get(key: K): Option[V] = if (key == key1) Some(value1) else if (key == key2) Some(value2) else if (key == key3) Some(value3) else None def iterator = Iterator((key1, value1), (key2, value2), (key3, value3)) - override def updated [B1 >: B] (key: A, value: B1): Map[A, B1] = + override def updated [V1 >: V] (key: K, value: V1): Map[K, V1] = if (key == key1) new Map3(key1, value, key2, value2, key3, value3) else if (key == key2) new Map3(key1, value1, key2, value, key3, value3) else if (key == key3) new Map3(key1, value1, key2, value2, key3, value) else new Map4(key1, value1, key2, value2, key3, value3, key, value) - def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2) - def - (key: A): Map[A, B] = + def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2) + def - (key: K): Map[K, V] = if (key == key1) new Map2(key2, value2, key3, value3) else if (key == key2) new Map2(key1, value1, key3, value3) else if (key == key3) new Map2(key1, value1, key2, value2) else this - override def foreach[U](f: ((A, B)) => U): Unit = { + override def foreach[U](f: ((K, V)) => U): Unit = { f((key1, value1)); f((key2, value2)); f((key3, value3)) } } - class Map4[A, +B](key1: A, value1: B, key2: A, value2: B, key3: A, value3: B, key4: A, value4: B) extends AbstractMap[A, B] with Map[A, B] with Serializable { + class Map4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends AbstractMap[K, V] with Map[K, V] with Serializable { override def size = 4 - override def apply(key: A) = + override def apply(key: K) = if (key == key1) value1 else if (key == key2) value2 else if (key == key3) value3 else if (key == key4) value4 else throw new NoSuchElementException("key not found: " + key) - override def contains(key: A) = (key == key1) || (key == key2) || (key == key3) || (key == key4) - def get(key: A): Option[B] = + override def contains(key: K) = (key == key1) || (key == key2) || (key == key3) || (key == key4) + def get(key: K): Option[V] = if (key == key1) Some(value1) else if (key == key2) Some(value2) else if (key == key3) Some(value3) else if (key == key4) Some(value4) else None def iterator = Iterator((key1, value1), (key2, value2), (key3, value3), (key4, value4)) - override def updated [B1 >: B] (key: A, value: B1): Map[A, B1] = + override def updated [V1 >: V] (key: K, value: V1): Map[K, V1] = if (key == key1) new Map4(key1, value, key2, value2, key3, value3, key4, value4) else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4) else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4) else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value) else new HashMap + ((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key, value)) - def + [B1 >: B](kv: (A, B1)): Map[A, B1] = updated(kv._1, kv._2) - def - (key: A): Map[A, B] = + def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2) + def - (key: K): Map[K, V] = if (key == key1) new Map3(key2, value2, key3, value3, key4, value4) else if (key == key2) new Map3(key1, value1, key3, value3, key4, value4) else if (key == key3) new Map3(key1, value1, key2, value2, key4, value4) else if (key == key4) new Map3(key1, value1, key2, value2, key3, value3) else this - override def foreach[U](f: ((A, B)) => U): Unit = { + override def foreach[U](f: ((K, V)) => U): Unit = { f((key1, value1)); f((key2, value2)); f((key3, value3)); f((key4, value4)) } } } /** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */ -abstract class AbstractMap[A, +B] extends scala.collection.AbstractMap[A, B] with Map[A, B] +abstract class AbstractMap[K, +V] extends scala.collection.AbstractMap[K, V] with Map[K, V] diff --git a/src/library/scala/collection/immutable/MapLike.scala b/src/library/scala/collection/immutable/MapLike.scala index bd5b9c9faf49..5867383b522e 100644 --- a/src/library/scala/collection/immutable/MapLike.scala +++ b/src/library/scala/collection/immutable/MapLike.scala @@ -14,16 +14,16 @@ import generic._ import parallel.immutable.ParMap /** - * A generic template for immutable maps from keys of type `A` - * to values of type `B`. + * A generic template for immutable maps from keys of type `K` + * to values of type `V`. * To implement a concrete map, you need to provide implementations of the * following methods (where `This` is the type of the actual map implementation): * * {{{ - * def get(key: A): Option[B] - * def iterator: Iterator[(A, B)] - * def + [B1 >: B](kv: (A, B)): Map[A, B1] - * def - (key: A): This + * def get(key: K): Option[V] + * def iterator: Iterator[(K, V)] + * def + [V1 >: V](kv: (K, V)): Map[K, V1] + * def - (key: K): This * }}} * * If you wish that transformer methods like `take`, `drop`, `filter` return the @@ -36,8 +36,8 @@ import parallel.immutable.ParMap * It is also good idea to override methods `foreach` and * `size` for efficiency. * - * @tparam A the type of the keys contained in this collection. - * @tparam B the type of the values associated with the keys. + * @tparam K the type of the keys contained in this collection. + * @tparam V the type of the values associated with the keys. * @tparam This The type of the actual map implementation. * * @author Martin Odersky @@ -46,26 +46,26 @@ import parallel.immutable.ParMap * @define Coll immutable.Map * @define coll immutable map */ -trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] - extends scala.collection.MapLike[A, B, This] - with Parallelizable[(A, B), ParMap[A, B]] +trait MapLike[K, +V, +This <: MapLike[K, V, This] with Map[K, V]] + extends scala.collection.MapLike[K, V, This] + with Parallelizable[(K, V), ParMap[K, V]] { self => - protected[this] override def parCombiner = ParMap.newCombiner[A, B] + protected[this] override def parCombiner = ParMap.newCombiner[K, V] /** A new immutable map containing updating this map with a given key/value mapping. * @param key the key * @param value the value * @return A new map with the new key/value mapping */ - override def updated [B1 >: B](key: A, value: B1): immutable.Map[A, B1] = this + ((key, value)) + override def updated [V1 >: V](key: K, value: V1): immutable.Map[K, V1] = this + ((key, value)) /** Add a key/value pair to this map, returning a new map. * @param kv the key/value pair. * @return A new map with the new binding added to this map. */ - def + [B1 >: B] (kv: (A, B1)): immutable.Map[A, B1] + def + [V1 >: V] (kv: (K, V1)): immutable.Map[K, V1] /** Adds two or more elements to this collection and returns * a new collection. @@ -75,7 +75,7 @@ self => * @param elems the remaining elements to add. * @return A new map with the new bindings added to this map. */ - override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): immutable.Map[A, B1] = + override def + [V1 >: V] (elem1: (K, V1), elem2: (K, V1), elems: (K, V1) *): immutable.Map[K, V1] = this + elem1 + elem2 ++ elems /** Adds a number of elements provided by a traversable object @@ -84,40 +84,40 @@ self => * @param xs the traversable object consisting of key-value pairs. * @return a new immutable map with the bindings of this map and those from `xs`. */ - override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): immutable.Map[A, B1] = - ((repr: immutable.Map[A, B1]) /: xs.seq) (_ + _) + override def ++[V1 >: V](xs: GenTraversableOnce[(K, V1)]): immutable.Map[K, V1] = + ((repr: immutable.Map[K, V1]) /: xs.seq) (_ + _) /** Filters this map by retaining only keys satisfying a predicate. * @param p the predicate used to test keys * @return an immutable map consisting only of those key value pairs of this map where the key satisfies * the predicate `p`. The resulting map wraps the original map without copying any elements. */ - override def filterKeys(p: A => Boolean): Map[A, B] = new FilteredKeys(p) with DefaultMap[A, B] + override def filterKeys(p: K => Boolean): Map[K, V] = new FilteredKeys(p) with DefaultMap[K, V] /** Transforms this map by applying a function to every retrieved value. * @param f the function used to transform values of this map. * @return a map view which maps every key of this map * to `f(this(key))`. The resulting map wraps the original map without copying any elements. */ - override def mapValues[C](f: B => C): Map[A, C] = new MappedValues(f) with DefaultMap[A, C] + override def mapValues[W](f: V => W): Map[K, W] = new MappedValues(f) with DefaultMap[K, W] /** Collects all keys of this map in a set. * @return a set containing all keys of this map. */ - override def keySet: immutable.Set[A] = new ImmutableDefaultKeySet + override def keySet: immutable.Set[K] = new ImmutableDefaultKeySet - protected class ImmutableDefaultKeySet extends super.DefaultKeySet with immutable.Set[A] { - override def + (elem: A): immutable.Set[A] = + protected class ImmutableDefaultKeySet extends super.DefaultKeySet with immutable.Set[K] { + override def + (elem: K): immutable.Set[K] = if (this(elem)) this - else immutable.Set[A]() ++ this + elem - override def - (elem: A): immutable.Set[A] = - if (this(elem)) immutable.Set[A]() ++ this - elem + else immutable.Set[K]() ++ this + elem + override def - (elem: K): immutable.Set[K] = + if (this(elem)) immutable.Set[K]() ++ this - elem else this // ImmutableDefaultKeySet is only protected, so we won't warn on override. // Someone could override in a way that makes widening not okay // (e.g. by overriding +, though the version in this class is fine) - override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] + override def toSet[B >: K]: Set[B] = this.asInstanceOf[Set[B]] } /** This function transforms all the values of mappings contained @@ -126,10 +126,9 @@ self => * @param f A function over keys and values * @return the updated map */ - def transform[C, That](f: (A, B) => C)(implicit bf: CanBuildFrom[This, (A, C), That]): That = { + def transform[W, That](f: (K, V) => W)(implicit bf: CanBuildFrom[This, (K, W), That]): That = { val b = bf(repr) for ((key, value) <- this) b += ((key, f(key, value))) b.result() } } - diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index 2ac3cb65b52e..460a8b8f77f8 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -20,15 +20,15 @@ import generic._ * @since 1.0 * @author Matthias Zenger */ -trait Map[A, B] - extends Iterable[(A, B)] -// with GenMap[A, B] - with scala.collection.Map[A, B] - with MapLike[A, B, Map[A, B]] { +trait Map[K, V] + extends Iterable[(K, V)] +// with GenMap[K, V] + with scala.collection.Map[K, V] + with MapLike[K, V, Map[K, V]] { - override def empty: Map[A, B] = Map.empty + override def empty: Map[K, V] = Map.empty - override def seq: Map[A, B] = this + override def seq: Map[K, V] = this /** The same map with a given default function. * @@ -37,7 +37,7 @@ trait Map[A, B] * @param d the function mapping keys to values, used for non-present keys * @return a wrapper of the map with a default value */ - def withDefault(d: A => B): mutable.Map[A, B] = new Map.WithDefault[A, B](this, d) + def withDefault(d: K => V): mutable.Map[K, V] = new Map.WithDefault[K, V](this, d) /** The same map with a given default value. * @@ -46,7 +46,7 @@ trait Map[A, B] * @param d default value used for non-present keys * @return a wrapper of the map with a default value */ - def withDefaultValue(d: B): mutable.Map[A, B] = new Map.WithDefault[A, B](this, x => d) + def withDefaultValue(d: V): mutable.Map[K, V] = new Map.WithDefault[K, V](this, x => d) } /** $factoryInfo @@ -56,25 +56,25 @@ trait Map[A, B] */ object Map extends MutableMapFactory[Map] { /** $canBuildFromInfo */ - implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), Map[A, B]] = new MapCanBuildFrom[A, B] + implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), Map[K, V]] = new MapCanBuildFrom[K, V] - def empty[A, B]: Map[A, B] = new HashMap[A, B] + def empty[K, V]: Map[K, V] = new HashMap[K, V] - class WithDefault[A, B](underlying: Map[A, B], d: A => B) extends scala.collection.Map.WithDefault(underlying, d) with Map[A, B] { - override def += (kv: (A, B)) = {underlying += kv; this} - def -= (key: A) = {underlying -= key; this} + class WithDefault[K, V](underlying: Map[K, V], d: K => V) extends scala.collection.Map.WithDefault(underlying, d) with Map[K, V] { + override def += (kv: (K, V)) = {underlying += kv; this} + def -= (key: K) = {underlying -= key; this} override def empty = new WithDefault(underlying.empty, d) - override def updated[B1 >: B](key: A, value: B1): WithDefault[A, B1] = new WithDefault[A, B1](underlying.updated[B1](key, value), d) - override def + [B1 >: B](kv: (A, B1)): WithDefault[A, B1] = updated(kv._1, kv._2) - override def - (key: A): WithDefault[A, B] = new WithDefault(underlying - key, d) + override def updated[V1 >: V](key: K, value: V1): WithDefault[K, V1] = new WithDefault[K, V1](underlying.updated[V1](key, value), d) + override def + [V1 >: V](kv: (K, V1)): WithDefault[K, V1] = updated(kv._1, kv._2) + override def - (key: K): WithDefault[K, V] = new WithDefault(underlying - key, d) /** If these methods aren't overridden to thread through the underlying map, * successive calls to withDefault* have no effect. */ - override def withDefault(d: A => B): mutable.Map[A, B] = new WithDefault[A, B](underlying, d) - override def withDefaultValue(d: B): mutable.Map[A, B] = new WithDefault[A, B](underlying, x => d) + override def withDefault(d: K => V): mutable.Map[K, V] = new WithDefault[K, V](underlying, d) + override def withDefaultValue(d: V): mutable.Map[K, V] = new WithDefault[K, V](underlying, x => d) } } /** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */ -abstract class AbstractMap[A, B] extends scala.collection.AbstractMap[A, B] with Map[A, B] +abstract class AbstractMap[K, V] extends scala.collection.AbstractMap[K, V] with Map[K, V] diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala index 949e5e3536bc..238b6d1be1f4 100644 --- a/src/library/scala/collection/mutable/MapLike.scala +++ b/src/library/scala/collection/mutable/MapLike.scala @@ -31,10 +31,10 @@ import scala.collection.parallel.mutable.ParMap * To implement a concrete mutable map, you need to provide * implementations of the following methods: * {{{ - * def get(key: A): Option[B] - * def iterator: Iterator[(A, B)] - * def += (kv: (A, B)): This - * def -= (key: A): This + * def get(key: K): Option[V] + * def iterator: Iterator[(K, V)] + * def += (kv: (K, V)): This + * def -= (key: K): This * }}} * If you wish that methods like `take`, `drop`, `filter` also return the same kind of map * you should also override: @@ -44,13 +44,13 @@ import scala.collection.parallel.mutable.ParMap * It is also good idea to override methods `foreach` and * `size` for efficiency. */ -trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] - extends scala.collection.MapLike[A, B, This] - with Builder[(A, B), This] - with Growable[(A, B)] - with Shrinkable[A] +trait MapLike[K, V, +This <: MapLike[K, V, This] with Map[K, V]] + extends scala.collection.MapLike[K, V, This] + with Builder[(K, V), This] + with Growable[(K, V)] + with Shrinkable[K] with Cloneable[This] - with Parallelizable[(A, B), ParMap[A, B]] + with Parallelizable[(K, V), ParMap[K, V]] { self => /** A common implementation of `newBuilder` for all mutable maps @@ -58,17 +58,17 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * * Overrides `MapLike` implementation for better efficiency. */ - override protected[this] def newBuilder: Builder[(A, B), This] = empty + override protected[this] def newBuilder: Builder[(K, V), This] = empty - protected[this] override def parCombiner = ParMap.newCombiner[A, B] + protected[this] override def parCombiner = ParMap.newCombiner[K, V] /** Converts this $coll to a sequence. * * ```Note```: assumes a fast `size` method. Subclasses should override if this is not true. */ - override def toSeq: collection.Seq[(A, B)] = { + override def toSeq: collection.Seq[(K, V)] = { // ArrayBuffer for efficiency, preallocated to the right size. - val result = new ArrayBuffer[(A, B)](size) + val result = new ArrayBuffer[(K, V)](size) foreach(result += _) result } @@ -84,7 +84,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * before the `put` operation was executed, or `None` if `key` * was not defined in the map before. */ - def put(key: A, value: B): Option[B] = { + def put(key: K, value: V): Option[V] = { val r = get(key) update(key, value) r @@ -97,7 +97,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @param key The key to update * @param value The new value */ - def update(key: A, value: B) { this += ((key, value)) } + def update(key: K, value: V) { this += ((key, value)) } /** Adds a new key/value pair to this map. * If the map already contains a @@ -105,7 +105,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @param kv the key/value pair. * @return the map itself */ - def += (kv: (A, B)): this.type + def += (kv: (K, V)): this.type /** Creates a new map consisting of all key/value pairs of the current map * plus a new pair of a given key and value. @@ -115,7 +115,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return A fresh immutable map with the binding from `key` to * `value` added to this map. */ - override def updated[B1 >: B](key: A, value: B1): Map[A, B1] = this + ((key, value)) + override def updated[V1 >: V](key: K, value: V1): Map[K, V1] = this + ((key, value)) /** Creates a new map containing a new key/value mapping and all the key/value mappings * of this map. @@ -126,7 +126,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return a new map containing mappings of this map and the mapping `kv`. */ @migration("`+` creates a new map. Use `+=` to add an element to this map and return that map itself.", "2.8.0") - def + [B1 >: B] (kv: (A, B1)): Map[A, B1] = clone().asInstanceOf[Map[A, B1]] += kv + def + [V1 >: V] (kv: (K, V1)): Map[K, V1] = clone().asInstanceOf[Map[K, V1]] += kv /** Creates a new map containing two or more key/value mappings and all the key/value * mappings of this map. @@ -139,8 +139,8 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return a new map containing mappings of this map and two or more specified mappings. */ @migration("`+` creates a new map. Use `+=` to add an element to this map and return that map itself.", "2.8.0") - override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): Map[A, B1] = - clone().asInstanceOf[Map[A, B1]] += elem1 += elem2 ++= elems + override def + [V1 >: V] (elem1: (K, V1), elem2: (K, V1), elems: (K, V1) *): Map[K, V1] = + clone().asInstanceOf[Map[K, V1]] += elem1 += elem2 ++= elems /** Creates a new map containing the key/value mappings provided by the specified traversable object * and all the key/value mappings of this map. @@ -151,8 +151,8 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return a new map containing mappings of this map and those provided by `xs`. */ @migration("`++` creates a new map. Use `++=` to add an element to this map and return that map itself.", "2.8.0") - override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1] = - clone().asInstanceOf[Map[A, B1]] ++= xs.seq + override def ++[V1 >: V](xs: GenTraversableOnce[(K, V1)]): Map[K, V1] = + clone().asInstanceOf[Map[K, V1]] ++= xs.seq /** Removes a key from this map, returning the value associated previously * with that key as an option. @@ -160,7 +160,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return an option value containing the value associated previously with `key`, * or `None` if `key` was not defined in the map before. */ - def remove(key: A): Option[B] = { + def remove(key: K): Option[V] = { val r = get(key) this -= key r @@ -170,7 +170,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @param key the key to be removed * @return the map itself. */ - def -= (key: A): this.type + def -= (key: K): this.type /** Creates a new map with all the key/value mappings of this map except the key/value mapping * with the specified key. @@ -179,7 +179,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return a new map with all the mappings of this map except that with a key `key`. */ @migration("`-` creates a new map. Use `-=` to remove an element from this map and return that map itself.", "2.8.0") - override def -(key: A): This = clone() -= key + override def -(key: K): This = clone() -= key /** Removes all bindings from the map. After this operation has completed, * the map will be empty. @@ -200,7 +200,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return the value associated with key (either previously or as a result * of executing the method). */ - def getOrElseUpdate(key: A, op: => B): B = + def getOrElseUpdate(key: K, op: => V): V = get(key) match { case Some(v) => v case None => val d = op; this(key) = d; d @@ -213,7 +213,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @param f the transformation to apply * @return the map itself. */ - def transform(f: (A, B) => B): this.type = { + def transform(f: (K, V) => V): this.type = { this.iterator foreach { case (key, value) => update(key, f(key, value)) } @@ -225,7 +225,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * * @param p The test predicate */ - def retain(p: (A, B) => Boolean): this.type = { + def retain(p: (K, V) => Boolean): this.type = { for ((k, v) <- this.toList) // SI-7269 toList avoids ConcurrentModificationException if (!p(k, v)) this -= k @@ -249,7 +249,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * with a key equal to `elem1`, `elem2` or any of `elems`. */ @migration("`-` creates a new map. Use `-=` to remove an element from this map and return that map itself.", "2.8.0") - override def -(elem1: A, elem2: A, elems: A*): This = + override def -(elem1: K, elem2: K, elems: K*): This = clone() -= elem1 -= elem2 --= elems /** Creates a new map with all the key/value mappings of this map except mappings with keys @@ -260,5 +260,5 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * with a key equal to a key from `xs`. */ @migration("`--` creates a new map. Use `--=` to remove an element from this map and return that map itself.", "2.8.0") - override def --(xs: GenTraversableOnce[A]): This = clone() --= xs.seq + override def --(xs: GenTraversableOnce[K]): This = clone() --= xs.seq } diff --git a/test/files/run/xMigration.check b/test/files/run/xMigration.check index cd860bf39490..1104dbea835f 100644 --- a/test/files/run/xMigration.check +++ b/test/files/run/xMigration.check @@ -11,7 +11,7 @@ scala> :setting -Xmigration:any scala> Map(1 -> "eis").values // warn :12: warning: method values in trait MapLike has changed semantics in version 2.8.0: -`values` returns `Iterable[B]` rather than `Iterator[B]`. +`values` returns `Iterable[V]` rather than `Iterator[V]`. Map(1 -> "eis").values // warn ^ res2: Iterable[String] = MapLike(eis) @@ -25,7 +25,7 @@ scala> :setting -Xmigration:2.7 scala> Map(1 -> "eis").values // warn :12: warning: method values in trait MapLike has changed semantics in version 2.8.0: -`values` returns `Iterable[B]` rather than `Iterator[B]`. +`values` returns `Iterable[V]` rather than `Iterator[V]`. Map(1 -> "eis").values // warn ^ res4: Iterable[String] = MapLike(eis) @@ -39,7 +39,7 @@ scala> :setting -Xmigration // same as :any scala> Map(1 -> "eis").values // warn :12: warning: method values in trait MapLike has changed semantics in version 2.8.0: -`values` returns `Iterable[B]` rather than `Iterator[B]`. +`values` returns `Iterable[V]` rather than `Iterator[V]`. Map(1 -> "eis").values // warn ^ res6: Iterable[String] = MapLike(eis) From cd9240ed524e69f01fcd872b9791754102c6530b Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Tue, 5 Jul 2016 12:37:04 +0200 Subject: [PATCH 128/153] SI-7301 Make tuple classes final This includes undoing the special case for `-Xfuture` introduced in https://github.com/scala/scala/pull/2299 and updating tests to take the new errors into account. --- src/build/genprod.scala | 3 +-- src/compiler/scala/tools/nsc/typechecker/Checkable.scala | 4 +--- src/library/scala/Tuple1.scala | 3 +-- src/library/scala/Tuple10.scala | 3 +-- src/library/scala/Tuple11.scala | 3 +-- src/library/scala/Tuple12.scala | 3 +-- src/library/scala/Tuple13.scala | 3 +-- src/library/scala/Tuple14.scala | 3 +-- src/library/scala/Tuple15.scala | 3 +-- src/library/scala/Tuple16.scala | 3 +-- src/library/scala/Tuple17.scala | 3 +-- src/library/scala/Tuple18.scala | 3 +-- src/library/scala/Tuple19.scala | 3 +-- src/library/scala/Tuple2.scala | 3 +-- src/library/scala/Tuple20.scala | 3 +-- src/library/scala/Tuple21.scala | 3 +-- src/library/scala/Tuple22.scala | 3 +-- src/library/scala/Tuple3.scala | 3 +-- src/library/scala/Tuple4.scala | 3 +-- src/library/scala/Tuple5.scala | 3 +-- src/library/scala/Tuple6.scala | 3 +-- src/library/scala/Tuple7.scala | 3 +-- src/library/scala/Tuple8.scala | 3 +-- src/library/scala/Tuple9.scala | 3 +-- test/files/neg/t7294.check | 6 +++++- test/files/neg/t7294.flags | 1 - test/files/neg/t7294b.check | 4 +--- test/files/neg/t7294b.flags | 1 - test/files/pos/t7294.scala | 6 ------ test/files/pos/tcpoly_bounds1.scala | 6 ++++-- test/files/run/t3888.check | 1 - test/files/run/t3888.scala | 5 +++-- 32 files changed, 37 insertions(+), 66 deletions(-) delete mode 100644 test/files/neg/t7294.flags delete mode 100644 test/files/neg/t7294b.flags delete mode 100644 test/files/pos/t7294.scala diff --git a/src/build/genprod.scala b/src/build/genprod.scala index f85a151ae534..fa48b020cc96 100644 --- a/src/build/genprod.scala +++ b/src/build/genprod.scala @@ -315,8 +315,7 @@ class Tuple(val i: Int) extends Group("Tuple") with Arity { * @constructor Create a new tuple with {i} elements.{idiomatic} {params} */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class {className}{covariantArgs}({fields}) +final case class {className}{covariantArgs}({fields}) extends {Product.className(i)}{invariantArgs} {{ override def toString() = "(" + {mkToString} + ")" diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala index 2b6a4c763a5c..215ee1c42bc6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala @@ -241,9 +241,7 @@ trait Checkable { private def isSealedOrFinal(sym: Symbol) = sym.isSealed || sym.isFinal private def isEffectivelyFinal(sym: Symbol): Boolean = ( // initialization important - sym.initialize.isEffectivelyFinalOrNotOverridden || ( - settings.future && isTupleSymbol(sym) // SI-7294 step into the future and treat TupleN as final. - ) + sym.initialize.isEffectivelyFinalOrNotOverridden ) def isNeverSubClass(sym1: Symbol, sym2: Symbol) = areIrreconcilableAsParents(sym1, sym2) diff --git a/src/library/scala/Tuple1.scala b/src/library/scala/Tuple1.scala index 5898b63e213d..5544a5f63d9c 100644 --- a/src/library/scala/Tuple1.scala +++ b/src/library/scala/Tuple1.scala @@ -15,8 +15,7 @@ package scala * @constructor Create a new tuple with 1 elements. * @param _1 Element 1 of this Tuple1 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple1[@specialized(Int, Long, Double) +T1](_1: T1) +final case class Tuple1[@specialized(Int, Long, Double) +T1](_1: T1) extends Product1[T1] { override def toString() = "(" + _1 + ")" diff --git a/src/library/scala/Tuple10.scala b/src/library/scala/Tuple10.scala index 2b0239561d2c..c57acb7c6e7f 100644 --- a/src/library/scala/Tuple10.scala +++ b/src/library/scala/Tuple10.scala @@ -24,8 +24,7 @@ package scala * @param _9 Element 9 of this Tuple10 * @param _10 Element 10 of this Tuple10 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10) +final case class Tuple10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10) extends Product10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + ")" diff --git a/src/library/scala/Tuple11.scala b/src/library/scala/Tuple11.scala index 0d5294d5471b..06360e6679ba 100644 --- a/src/library/scala/Tuple11.scala +++ b/src/library/scala/Tuple11.scala @@ -25,8 +25,7 @@ package scala * @param _10 Element 10 of this Tuple11 * @param _11 Element 11 of this Tuple11 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11) +final case class Tuple11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11) extends Product11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + ")" diff --git a/src/library/scala/Tuple12.scala b/src/library/scala/Tuple12.scala index d36c8275c1d0..e223de104d95 100644 --- a/src/library/scala/Tuple12.scala +++ b/src/library/scala/Tuple12.scala @@ -26,8 +26,7 @@ package scala * @param _11 Element 11 of this Tuple12 * @param _12 Element 12 of this Tuple12 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12) +final case class Tuple12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12) extends Product12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + diff --git a/src/library/scala/Tuple13.scala b/src/library/scala/Tuple13.scala index edc37456fe19..56e12b96b676 100644 --- a/src/library/scala/Tuple13.scala +++ b/src/library/scala/Tuple13.scala @@ -27,8 +27,7 @@ package scala * @param _12 Element 12 of this Tuple13 * @param _13 Element 13 of this Tuple13 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13) +final case class Tuple13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13) extends Product13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + diff --git a/src/library/scala/Tuple14.scala b/src/library/scala/Tuple14.scala index 9896e736c9d4..53dd4d79bbf3 100644 --- a/src/library/scala/Tuple14.scala +++ b/src/library/scala/Tuple14.scala @@ -28,8 +28,7 @@ package scala * @param _13 Element 13 of this Tuple14 * @param _14 Element 14 of this Tuple14 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14) +final case class Tuple14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14) extends Product14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + diff --git a/src/library/scala/Tuple15.scala b/src/library/scala/Tuple15.scala index 45cd4f751f8f..0aca96d00da0 100644 --- a/src/library/scala/Tuple15.scala +++ b/src/library/scala/Tuple15.scala @@ -29,8 +29,7 @@ package scala * @param _14 Element 14 of this Tuple15 * @param _15 Element 15 of this Tuple15 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15) +final case class Tuple15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15) extends Product15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + diff --git a/src/library/scala/Tuple16.scala b/src/library/scala/Tuple16.scala index 2e370a5b31b8..d4c0c318070f 100644 --- a/src/library/scala/Tuple16.scala +++ b/src/library/scala/Tuple16.scala @@ -30,8 +30,7 @@ package scala * @param _15 Element 15 of this Tuple16 * @param _16 Element 16 of this Tuple16 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16) +final case class Tuple16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16) extends Product16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + diff --git a/src/library/scala/Tuple17.scala b/src/library/scala/Tuple17.scala index 2242a15fda38..47df6cb59f07 100644 --- a/src/library/scala/Tuple17.scala +++ b/src/library/scala/Tuple17.scala @@ -31,8 +31,7 @@ package scala * @param _16 Element 16 of this Tuple17 * @param _17 Element 17 of this Tuple17 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17) +final case class Tuple17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17) extends Product17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + diff --git a/src/library/scala/Tuple18.scala b/src/library/scala/Tuple18.scala index 68f245c6cefa..464b08fb2840 100644 --- a/src/library/scala/Tuple18.scala +++ b/src/library/scala/Tuple18.scala @@ -32,8 +32,7 @@ package scala * @param _17 Element 17 of this Tuple18 * @param _18 Element 18 of this Tuple18 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18) +final case class Tuple18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18) extends Product18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + diff --git a/src/library/scala/Tuple19.scala b/src/library/scala/Tuple19.scala index a8a49549fbc7..d64b3920b441 100644 --- a/src/library/scala/Tuple19.scala +++ b/src/library/scala/Tuple19.scala @@ -33,8 +33,7 @@ package scala * @param _18 Element 18 of this Tuple19 * @param _19 Element 19 of this Tuple19 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19) +final case class Tuple19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19) extends Product19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala index 9ea1469c5c3d..5faa4e982150 100644 --- a/src/library/scala/Tuple2.scala +++ b/src/library/scala/Tuple2.scala @@ -16,8 +16,7 @@ package scala * @param _1 Element 1 of this Tuple2 * @param _2 Element 2 of this Tuple2 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple2[@specialized(Int, Long, Double, Char, Boolean/*, AnyRef*/) +T1, @specialized(Int, Long, Double, Char, Boolean/*, AnyRef*/) +T2](_1: T1, _2: T2) +final case class Tuple2[@specialized(Int, Long, Double, Char, Boolean/*, AnyRef*/) +T1, @specialized(Int, Long, Double, Char, Boolean/*, AnyRef*/) +T2](_1: T1, _2: T2) extends Product2[T1, T2] { override def toString() = "(" + _1 + "," + _2 + ")" diff --git a/src/library/scala/Tuple20.scala b/src/library/scala/Tuple20.scala index 0118d382ab6f..a96c41baa551 100644 --- a/src/library/scala/Tuple20.scala +++ b/src/library/scala/Tuple20.scala @@ -34,8 +34,7 @@ package scala * @param _19 Element 19 of this Tuple20 * @param _20 Element 20 of this Tuple20 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20) +final case class Tuple20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20) extends Product20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + diff --git a/src/library/scala/Tuple21.scala b/src/library/scala/Tuple21.scala index ceae94af41b0..6f240d1fba7f 100644 --- a/src/library/scala/Tuple21.scala +++ b/src/library/scala/Tuple21.scala @@ -35,8 +35,7 @@ package scala * @param _20 Element 20 of this Tuple21 * @param _21 Element 21 of this Tuple21 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20, _21: T21) +final case class Tuple21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20, _21: T21) extends Product21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + diff --git a/src/library/scala/Tuple22.scala b/src/library/scala/Tuple22.scala index ecd567a710e0..681b709f6578 100644 --- a/src/library/scala/Tuple22.scala +++ b/src/library/scala/Tuple22.scala @@ -36,8 +36,7 @@ package scala * @param _21 Element 21 of this Tuple22 * @param _22 Element 22 of this Tuple22 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20, _21: T21, _22: T22) +final case class Tuple22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +T13, +T14, +T15, +T16, +T17, +T18, +T19, +T20, +T21, +T22](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9, _10: T10, _11: T11, _12: T12, _13: T13, _14: T14, _15: T15, _16: T16, _17: T17, _18: T18, _19: T19, _20: T20, _21: T21, _22: T22) extends Product22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + diff --git a/src/library/scala/Tuple3.scala b/src/library/scala/Tuple3.scala index 6e71d3ae8c23..86f8f7e1a4b3 100644 --- a/src/library/scala/Tuple3.scala +++ b/src/library/scala/Tuple3.scala @@ -17,8 +17,7 @@ package scala * @param _2 Element 2 of this Tuple3 * @param _3 Element 3 of this Tuple3 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) +final case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) extends Product3[T1, T2, T3] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")" diff --git a/src/library/scala/Tuple4.scala b/src/library/scala/Tuple4.scala index 4c84cfc674cb..f3266c262c41 100644 --- a/src/library/scala/Tuple4.scala +++ b/src/library/scala/Tuple4.scala @@ -18,8 +18,7 @@ package scala * @param _3 Element 3 of this Tuple4 * @param _4 Element 4 of this Tuple4 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple4[+T1, +T2, +T3, +T4](_1: T1, _2: T2, _3: T3, _4: T4) +final case class Tuple4[+T1, +T2, +T3, +T4](_1: T1, _2: T2, _3: T3, _4: T4) extends Product4[T1, T2, T3, T4] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + ")" diff --git a/src/library/scala/Tuple5.scala b/src/library/scala/Tuple5.scala index fe8e853f1212..e6ac0a62452c 100644 --- a/src/library/scala/Tuple5.scala +++ b/src/library/scala/Tuple5.scala @@ -19,8 +19,7 @@ package scala * @param _4 Element 4 of this Tuple5 * @param _5 Element 5 of this Tuple5 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple5[+T1, +T2, +T3, +T4, +T5](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5) +final case class Tuple5[+T1, +T2, +T3, +T4, +T5](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5) extends Product5[T1, T2, T3, T4, T5] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + ")" diff --git a/src/library/scala/Tuple6.scala b/src/library/scala/Tuple6.scala index 6bf1c73d4be9..cf69b9c10a6a 100644 --- a/src/library/scala/Tuple6.scala +++ b/src/library/scala/Tuple6.scala @@ -20,8 +20,7 @@ package scala * @param _5 Element 5 of this Tuple6 * @param _6 Element 6 of this Tuple6 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple6[+T1, +T2, +T3, +T4, +T5, +T6](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6) +final case class Tuple6[+T1, +T2, +T3, +T4, +T5, +T6](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6) extends Product6[T1, T2, T3, T4, T5, T6] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + ")" diff --git a/src/library/scala/Tuple7.scala b/src/library/scala/Tuple7.scala index ea42709cb7a3..4f0200fe238f 100644 --- a/src/library/scala/Tuple7.scala +++ b/src/library/scala/Tuple7.scala @@ -21,8 +21,7 @@ package scala * @param _6 Element 6 of this Tuple7 * @param _7 Element 7 of this Tuple7 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7) +final case class Tuple7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7) extends Product7[T1, T2, T3, T4, T5, T6, T7] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + ")" diff --git a/src/library/scala/Tuple8.scala b/src/library/scala/Tuple8.scala index c24f9454e0ba..ebd9f7025264 100644 --- a/src/library/scala/Tuple8.scala +++ b/src/library/scala/Tuple8.scala @@ -22,8 +22,7 @@ package scala * @param _7 Element 7 of this Tuple8 * @param _8 Element 8 of this Tuple8 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8) +final case class Tuple8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8) extends Product8[T1, T2, T3, T4, T5, T6, T7, T8] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + ")" diff --git a/src/library/scala/Tuple9.scala b/src/library/scala/Tuple9.scala index ed02b30df2bd..854fe97b4401 100644 --- a/src/library/scala/Tuple9.scala +++ b/src/library/scala/Tuple9.scala @@ -23,8 +23,7 @@ package scala * @param _8 Element 8 of this Tuple9 * @param _9 Element 9 of this Tuple9 */ -@deprecatedInheritance("Tuples will be made final in a future version.", "2.11.0") -case class Tuple9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9) +final case class Tuple9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](_1: T1, _2: T2, _3: T3, _4: T4, _5: T5, _6: T6, _7: T7, _8: T8, _9: T9) extends Product9[T1, T2, T3, T4, T5, T6, T7, T8, T9] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + ")" diff --git a/test/files/neg/t7294.check b/test/files/neg/t7294.check index f15289c1c01a..a308f2457d4b 100644 --- a/test/files/neg/t7294.check +++ b/test/files/neg/t7294.check @@ -1,6 +1,10 @@ t7294.scala:4: warning: fruitless type test: a value of type (Int, Int) cannot also be a Seq[A] (1, 2) match { case Seq() => 0; case _ => 1 } ^ -error: No warnings can be incurred under -Xfatal-warnings. +t7294.scala:4: error: pattern type is incompatible with expected type; + found : Seq[A] + required: (Int, Int) + (1, 2) match { case Seq() => 0; case _ => 1 } + ^ one warning found one error found diff --git a/test/files/neg/t7294.flags b/test/files/neg/t7294.flags deleted file mode 100644 index 3f3381a45bde..000000000000 --- a/test/files/neg/t7294.flags +++ /dev/null @@ -1 +0,0 @@ --Xfuture -Xfatal-warnings diff --git a/test/files/neg/t7294b.check b/test/files/neg/t7294b.check index 707266f0cccf..3390cb72787f 100644 --- a/test/files/neg/t7294b.check +++ b/test/files/neg/t7294b.check @@ -1,6 +1,4 @@ -t7294b.scala:1: warning: inheritance from class Tuple2 in package scala is deprecated (since 2.11.0): Tuples will be made final in a future version. +t7294b.scala:1: error: illegal inheritance from final class Tuple2 class C extends Tuple2[Int, Int](0, 0) ^ -error: No warnings can be incurred under -Xfatal-warnings. -one warning found one error found diff --git a/test/files/neg/t7294b.flags b/test/files/neg/t7294b.flags deleted file mode 100644 index d1b831ea87cd..000000000000 --- a/test/files/neg/t7294b.flags +++ /dev/null @@ -1 +0,0 @@ --deprecation -Xfatal-warnings \ No newline at end of file diff --git a/test/files/pos/t7294.scala b/test/files/pos/t7294.scala deleted file mode 100644 index ccac2b14005f..000000000000 --- a/test/files/pos/t7294.scala +++ /dev/null @@ -1,6 +0,0 @@ -object Test { - // no fruitless warning as Tuple2 isn't (yet) final. - // The corresponding `neg` test will treat it as final - // for the purposes of these tests under -Xfuture. - (1, 2) match { case Seq() => 0; case _ => 1 } -} diff --git a/test/files/pos/tcpoly_bounds1.scala b/test/files/pos/tcpoly_bounds1.scala index 63263cb15290..4f52f55cb61e 100644 --- a/test/files/pos/tcpoly_bounds1.scala +++ b/test/files/pos/tcpoly_bounds1.scala @@ -1,7 +1,9 @@ -class Foo[t[x]<: Tuple2[Int, x]] +case class T2[+T1, +T2](_1: T1, _2: T2) extends Product2[T1, T2] + +class Foo[t[x]<: T2[Int, x]] // -class MyPair[z](a: Int, b: z) extends Tuple2[Int, z](a,b) +class MyPair[z](a: Int, b: z) extends T2[Int, z](a,b) object foo extends Foo[MyPair] diff --git a/test/files/run/t3888.check b/test/files/run/t3888.check index 6fda32d713ea..e69de29bb2d1 100644 --- a/test/files/run/t3888.check +++ b/test/files/run/t3888.check @@ -1 +0,0 @@ -warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t3888.scala b/test/files/run/t3888.scala index 8701b42ff0d4..b1932ffb20bc 100644 --- a/test/files/run/t3888.scala +++ b/test/files/run/t3888.scala @@ -1,3 +1,4 @@ +case class Tuple2[+T1, +T2](_1: T1, _2: T2) extends Product2[T1, T2] // in a match, which notion of equals prevails? // extending Tuple doesn't seem to be at issue here. @@ -7,13 +8,13 @@ object Test { private[this] val T2 = T1 def m1 = - (1, 2) match { + Tuple2(1, 2) match { case T1 => true case _ => false } def m2 = - (1, 2) match { + Tuple2(1, 2) match { case T2 => true case _ => false } From 3285c47d00ffeb2f9920556486bd3e460f9f5608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pociecha?= Date: Tue, 12 Jul 2016 16:48:02 +0200 Subject: [PATCH 129/153] Remove redundant 'the' in IntelliJ's README.md --- src/intellij/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intellij/README.md b/src/intellij/README.md index 41fef0418362..650d91e5d104 100644 --- a/src/intellij/README.md +++ b/src/intellij/README.md @@ -60,7 +60,7 @@ breakpoints within the Scala compiler. ## Running the Compiler and REPL You can create run/debug configurations to run the compiler and REPL directly within -IntelliJ, which might accelerate development and debugging of the the compiler. +IntelliJ, which might accelerate development and debugging of the compiler. To debug the Scala codebase you can also use "Remote" debug configuration and pass the corresponding arguments to the jvm running the compiler / program. From d33f2993782c259831e10beacc8274424b3a6250 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 8 Jul 2016 10:11:07 +0200 Subject: [PATCH 130/153] SI-9849 set privateWithin on default getters A default getter get the same access flag (private / protected) as the method whose default it implements. However, we forgot to set the privateWithin flag, which defines the scope in a qualified private / protected modifier. For a private[p], the default getter was therefore public, which is less restricted (a private[p] method has privateWithin set to p, but the private flag is not set). For a protected[p], the default getter was protected, which is more restricted. --- .../scala/tools/nsc/typechecker/Namers.scala | 2 +- test/files/neg/t9849.check | 7 +++++++ test/files/neg/t9849.scala | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/files/neg/t9849.check create mode 100644 test/files/neg/t9849.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 9c1ba7ced1d7..ad9377f8b4bd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1346,7 +1346,7 @@ trait Namers extends MethodSynthesis { val defRhs = rvparam.rhs val defaultTree = atPos(vparam.pos.focus) { - DefDef(Modifiers(paramFlagsToDefaultGetter(meth.flags)) | oflag, name, defTparams, defVparamss, defTpt, defRhs) + DefDef(Modifiers(paramFlagsToDefaultGetter(meth.flags), ddef.mods.privateWithin) | oflag, name, defTparams, defVparamss, defTpt, defRhs) } if (!isConstr) methOwner.resetFlag(INTERFACE) // there's a concrete member now diff --git a/test/files/neg/t9849.check b/test/files/neg/t9849.check new file mode 100644 index 000000000000..7b4715084648 --- /dev/null +++ b/test/files/neg/t9849.check @@ -0,0 +1,7 @@ +t9849.scala:14: error: method h in object O cannot be accessed in object p.O + O.h() + ^ +t9849.scala:15: error: method h$default$1 in object O cannot be accessed in object p.O + O.h$default$1 + ^ +two errors found diff --git a/test/files/neg/t9849.scala b/test/files/neg/t9849.scala new file mode 100644 index 000000000000..bcd18b6916d9 --- /dev/null +++ b/test/files/neg/t9849.scala @@ -0,0 +1,16 @@ +package p + +object O { + protected[p] def f(x: Int = 1) = x + private[p] def g(x: Int = 1) = x + private def h(x: Int = 1) = x +} + +object Test { + O.f() + O.f$default$1 + O.g() + O.g$default$1 + O.h() + O.h$default$1 +} From d386e802d53ab616a8a6005c89a9be30ab5526d8 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 12 Jul 2016 19:45:32 +1000 Subject: [PATCH 131/153] SI-9855 Fix regression in extractor pattern translation In faa5ae6, I changed the pattern matchers code generator to use stable references (`Ident`-s with the singleton type, rather than the widened type) to the synthetic vals used to store intermediate results ("binders"). In the case where the scrutinee matched the unapply parameter type of some extractor pattern, but the pattern subsequently failed, this led to an regression. It turns out that this was due to the way that the type of the binder was mutated to upcast to the exact type of a subsequent pattern in `ensureConformsTo`: https://github.com/scala/scala/blob/953559988/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala#L165-L174 This was added in 32c57329a as a workaround for the problem caused in t6664.scala, when the binder type was `KList with KCons`, and the code generator wasn't able to find the case field accessors for `KCons` in the decls. The change to use stable references meant that this mutation was now observed in another part of the tree, as opposed to the 2.11.8 situation, where we had used the original, sharper type of the binder eagerly to assign to the `Ident` that referred to it. This led to a tree: Assign(Ident(x3), Ident(x1).setType(x1.tpe) Now that we instead refer generate: Assign(Ident(x3), Ident(x1).setType(stableTypeFor(x1)) and we don't typecheck this until after the mutation of `x1.symbol.info`, we can get a type error. This commit removes this mutation of the binder type altogether, and instead uses `aligner.wholeType`, which is based on the result type of the `Apply(TypeTree(MethodType(params, resultType))` that encodes a typechecked constructor pattern. In `t6624.scala`, this is `KCons`, the case class that has the extractors as its decls. --- .../nsc/transform/patmat/MatchTranslation.scala | 17 +++-------------- test/files/pos/t9855.scala | 10 ++++++++++ test/files/pos/t9855b.scala | 16 ++++++++++++++++ test/files/run/t6288.check | 6 +++--- 4 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 test/files/pos/t9855.scala create mode 100644 test/files/pos/t9855b.scala diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala index e12b8548a8f4..5750f8f7e769 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala @@ -125,7 +125,7 @@ trait MatchTranslation { // TODO: paramType may contain unbound type params (run/t2800, run/t3530) val makers = ( // Statically conforms to paramType - if (this ensureConformsTo paramType) treeMaker(binder, false, pos) :: Nil + if (tpe <:< paramType) treeMaker(binder, false, pos) :: Nil else typeTest :: extraction :: Nil ) step(makers: _*)(extractor.subBoundTrees: _*) @@ -162,16 +162,6 @@ trait MatchTranslation { setVarInfo(binder, paramType) true } - // If <:< but not =:=, no type test needed, but the tree maker relies on the binder having - // exactly paramType (and not just some type compatible with it.) SI-6624 shows this is necessary - // because apparently patBinder may have an unfortunate type (.decls don't have the case field - // accessors) TODO: get to the bottom of this -- I assume it happens when type checking - // infers a weird type for an unapply call. By going back to the parameterType for the - // extractor call we get a saner type, so let's just do that for now. - def ensureConformsTo(paramType: Type): Boolean = ( - (tpe =:= paramType) - || (tpe <:< paramType) && setInfo(paramType) - ) private def concreteType = tpe.bounds.hi private def unbound = unbind(tree) @@ -396,7 +386,6 @@ trait MatchTranslation { /** Create the TreeMaker that embodies this extractor call * - * `binder` has been casted to `paramType` if necessary * `binderKnownNonNull` indicates whether the cast implies `binder` cannot be null * when `binderKnownNonNull` is `true`, `ProductExtractorTreeMaker` does not do a (redundant) null check on binder */ @@ -502,7 +491,7 @@ trait MatchTranslation { * when `binderKnownNonNull` is `true`, `ProductExtractorTreeMaker` does not do a (redundant) null check on binder */ def treeMaker(binder: Symbol, binderKnownNonNull: Boolean, pos: Position): TreeMaker = { - val paramAccessors = binder.constrParamAccessors + val paramAccessors = aligner.wholeType.typeSymbol.constrParamAccessors val numParams = paramAccessors.length def paramAccessorAt(subPatIndex: Int) = paramAccessors(math.min(subPatIndex, numParams - 1)) // binders corresponding to mutable fields should be stored (SI-5158, SI-6070) @@ -531,7 +520,7 @@ trait MatchTranslation { // reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component override protected def tupleSel(binder: Symbol)(i: Int): Tree = { - val accessors = binder.caseFieldAccessors + val accessors = aligner.wholeType.typeSymbol.caseFieldAccessors if (accessors isDefinedAt (i-1)) gen.mkAttributedStableRef(binder) DOT accessors(i-1) else codegen.tupleSel(binder)(i) // this won't type check for case classes, as they do not inherit ProductN } diff --git a/test/files/pos/t9855.scala b/test/files/pos/t9855.scala new file mode 100644 index 000000000000..b6ac3e2432cd --- /dev/null +++ b/test/files/pos/t9855.scala @@ -0,0 +1,10 @@ +class C { + def xx(verb: String, a: Array[Int]) { + val reYYYY = """(\d\d\d\d)""".r + verb match { + case "time" if a.isEmpty => + case "time" => + case reYYYY(y) => + } + } +} diff --git a/test/files/pos/t9855b.scala b/test/files/pos/t9855b.scala new file mode 100644 index 000000000000..30c58be3dcd1 --- /dev/null +++ b/test/files/pos/t9855b.scala @@ -0,0 +1,16 @@ +object Test { + var FALSE = false + def main(args: Array[String]): Unit = { + val SomeB = new B + new B() match { + case SomeB if FALSE => + case SomeB => + case Ext(_) => + } + } +} +object Ext { + def unapply(s: A) = Some(()) +} +class A +class B extends A diff --git a/test/files/run/t6288.check b/test/files/run/t6288.check index 67877fd56d6b..7933f516a8a4 100644 --- a/test/files/run/t6288.check +++ b/test/files/run/t6288.check @@ -7,7 +7,7 @@ }; [21]def unapply([29]z: [32]): [21]Option[Int] = [56][52][52]scala.Some.apply[[52]Int]([58]-1); [64]{ - [64]case val x1: [64]Any = [64]""; + [64]case val x1: [64]String = [64]""; [64]case5()[84]{ [84] val o7: [84]Option[Int] = [84][84]Case3.unapply([84]x1); [84]if ([84]o7.isEmpty.unary_!) @@ -30,7 +30,7 @@ }; [127]def unapplySeq([138]z: [141]): [127]Option[List[Int]] = [167]scala.None; [175]{ - [175]case val x1: [175]Any = [175]""; + [175]case val x1: [175]String = [175]""; [175]case5()[195]{ [195] val o7: [195]Option[List[Int]] = [195][195]Case4.unapplySeq([195]x1); [195]if ([195][195]o7.isEmpty.unary_!.&&([195][195][195][195]o7.get.!=([195]null).&&([195][195][195][195]o7.get.lengthCompare([195]1).==([195]0)))) @@ -53,7 +53,7 @@ }; [238]def unapply([246]z: [249]): [238]Boolean = [265]true; [273]{ - [273]case val x1: [273]Any = [273]""; + [273]case val x1: [273]String = [273]""; [273]case5()[293]{ [293] val o7: [293]Option[List[Int]] = [293][293]Case4.unapplySeq([293]x1); [293]if ([293][293]o7.isEmpty.unary_!.&&([293][293][293][293]o7.get.!=([293]null).&&([293][293][293][293]o7.get.lengthCompare([293]0).==([293]0)))) From f806073d32a476d156f1b3ec24c17f35ed65b4c3 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 14 Jul 2016 11:50:22 +1000 Subject: [PATCH 132/153] SD-183 Make refinement classes ineligible as SAMs Only non-refinement class types need apply, which is the same restriction that we levy on parent types of a class. ``` scala> class C; class D extends C; type CD = C with D; class E extends CD :11: error: class type required but C with D found class C; class D extends C; type CD = C with D; class E extends CD ^ scala> class C; class D extends C; type DC = D with C; class E extends DC :11: error: class type required but D with C found class C; class D extends C; type DC = D with C; class E extends DC ^ ``` Prior to this change: ``` scala> trait T { def t(a: Any): Any }; trait U; abstract class C extends T defined trait T defined trait U defined class C ```` For indy-based lambdas: ``` scala> val tu: T with U = x => x tu: T with U = $$Lambda$1812/317644782@3c3c4a71 scala> tu: U java.lang.ClassCastException: $$Lambda$1812/317644782 cannot be cast to U ... 30 elided ``` For anon class based lambdas: ``` scala> ((x => x): C with U) :14: error: class type required but C with U found ((x => x): C with U) ^ scala> implicit def anyToCWithU(a: Any): C with U = new C with U { def t(a: Any) = a } warning: there was one feature warning; re-run with -feature for details anyToCWithU: (a: Any)C with U scala> (((x: Any) => x): C with U) // SAM chosen but fails to typecheck the expansion uncurry :17: error: class type required but C with U found (((x: Any) => x): C with U) // SAM chosen but fails to typecheck the expansion uncurry ^ ``` Fixes https://github.com/scala/scala-dev/issues/183 While it is tempting to special case refinement classes with no decls by flattening their parents into the parents of the lambda. But there are some subtle issues at play with lineriazation order, as Martin pointed out when I brought this up before: http://www.scala-lang.org/old/node/6817.html --- .../scala/reflect/internal/Definitions.scala | 4 +-- test/files/neg/sammy_restrictions.check | 33 ++++++++++++------- test/files/neg/sammy_restrictions.scala | 7 +++- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index fe6d88e7c749..0342daf11390 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -837,9 +837,9 @@ trait Definitions extends api.StandardDefinitions { * The class defining the method is a supertype of `tp` that * has a public no-arg primary constructor. */ - def samOf(tp: Type): Symbol = if (!doSam) NoSymbol else { + def samOf(tp: Type): Symbol = if (!doSam) NoSymbol else if (!isNonRefinementClassType(unwrapToClass(tp))) NoSymbol else { // look at erased type because we (only) care about what ends up in bytecode - // (e.g., an alias type or intersection type is fine as long as the intersection dominator compiles to an interface) + // (e.g., an alias type is fine as long as is compiles to a single-abstract-method) val tpSym: Symbol = erasure.javaErasure(tp).typeSymbol if (tpSym.exists && tpSym.isClass diff --git a/test/files/neg/sammy_restrictions.check b/test/files/neg/sammy_restrictions.check index 09579cbe212d..0225c61ac1c3 100644 --- a/test/files/neg/sammy_restrictions.check +++ b/test/files/neg/sammy_restrictions.check @@ -1,51 +1,62 @@ -sammy_restrictions.scala:35: error: type mismatch; +sammy_restrictions.scala:38: error: type mismatch; found : () => Int required: NoAbstract (() => 0) : NoAbstract ^ -sammy_restrictions.scala:36: error: type mismatch; +sammy_restrictions.scala:39: error: type mismatch; found : Int => Int required: TwoAbstract ((x: Int) => 0): TwoAbstract ^ -sammy_restrictions.scala:37: error: type mismatch; +sammy_restrictions.scala:40: error: type mismatch; found : Int => Int required: NoEmptyConstructor ((x: Int) => 0): NoEmptyConstructor ^ -sammy_restrictions.scala:38: error: type mismatch; +sammy_restrictions.scala:41: error: type mismatch; found : Int => Int required: MultipleConstructorLists ((x: Int) => 0): MultipleConstructorLists ^ -sammy_restrictions.scala:39: error: type mismatch; +sammy_restrictions.scala:42: error: type mismatch; found : Int => Int required: OneEmptySecondaryConstructor ((x: Int) => 0): OneEmptySecondaryConstructor // derived class must have an empty *primary* to call. ^ -sammy_restrictions.scala:40: error: type mismatch; +sammy_restrictions.scala:43: error: type mismatch; found : Int => Int required: MultipleMethodLists ((x: Int) => 0): MultipleMethodLists ^ -sammy_restrictions.scala:41: error: type mismatch; +sammy_restrictions.scala:44: error: type mismatch; found : Int => Int required: ImplicitConstructorParam ((x: Int) => 0): ImplicitConstructorParam ^ -sammy_restrictions.scala:42: error: type mismatch; +sammy_restrictions.scala:45: error: type mismatch; found : Int => Int required: ImplicitMethodParam ((x: Int) => 0): ImplicitMethodParam ^ -sammy_restrictions.scala:43: error: type mismatch; +sammy_restrictions.scala:46: error: type mismatch; found : Int => Int required: PolyMethod ((x: Int) => 0): PolyMethod ^ -sammy_restrictions.scala:44: error: type mismatch; +sammy_restrictions.scala:47: error: type mismatch; found : Int => Int required: SelfTp ((x: Int) => 0): SelfTp ^ -10 errors found +sammy_restrictions.scala:48: error: type mismatch; + found : Int => Int + required: T1 with U1 + ((x: Int) => 0): T1 with U1 + ^ +sammy_restrictions.scala:49: error: type mismatch; + found : Int => Int + required: Test.NonClassTypeRefinement + (which expands to) DerivedOneAbstract with OneAbstract + ((x: Int) => 0): NonClassTypeRefinement + ^ +12 errors found diff --git a/test/files/neg/sammy_restrictions.scala b/test/files/neg/sammy_restrictions.scala index ff2c16b67913..dee4f1f24739 100644 --- a/test/files/neg/sammy_restrictions.scala +++ b/test/files/neg/sammy_restrictions.scala @@ -27,9 +27,12 @@ abstract class DerivedOneAbstract extends OneAbstract abstract class SelfTp { self: NoAbstract => def ap(a: Int): Any } abstract class SelfVar { self => def ap(a: Int): Any } +trait T1 { def t(a: Int): Int }; trait U1 + object Test { implicit val s: String = "" - type NonClassType = DerivedOneAbstract with OneAbstract + type NonClassTypeRefinement = DerivedOneAbstract with OneAbstract + type NonClassType = DerivedOneAbstract // errors: (() => 0) : NoAbstract @@ -42,6 +45,8 @@ object Test { ((x: Int) => 0): ImplicitMethodParam ((x: Int) => 0): PolyMethod ((x: Int) => 0): SelfTp + ((x: Int) => 0): T1 with U1 + ((x: Int) => 0): NonClassTypeRefinement // allowed: ((x: Int) => 0): OneEmptyConstructor From 841fb2559b47259f9e5dc92a390fb4c7760ac218 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 14 Jul 2016 18:39:24 +0100 Subject: [PATCH 133/153] Deprecate and rename Left#a/Right#b to Left#value/Right#value --- src/library/scala/util/Either.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index 5c61d83a1a07..2f1e5d5c33a7 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -345,9 +345,11 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * @author Tony Morris, Workingmouse * @version 1.0, 11/10/2008 */ -final case class Left[+A, +B](a: A) extends Either[A, B] { +final case class Left[+A, +B](@deprecatedName('a, "2.12.0") value: A) extends Either[A, B] { def isLeft = true def isRight = false + + @deprecated("Use .value instead.", "2.12.0") def a: A = value } /** @@ -356,9 +358,11 @@ final case class Left[+A, +B](a: A) extends Either[A, B] { * @author Tony Morris, Workingmouse * @version 1.0, 11/10/2008 */ -final case class Right[+A, +B](b: B) extends Either[A, B] { +final case class Right[+A, +B](@deprecatedName('b, "2.12.0") value: B) extends Either[A, B] { def isLeft = false def isRight = true + + @deprecated("Use .value instead.", "2.12.0") def b: B = value } object Either { From 26758054f80081a2fec32ed1c7d3fc92efeacb31 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 13 Jul 2016 15:35:31 +0100 Subject: [PATCH 134/153] Deprecated and rename Some#x to Some#value --- src/library/scala/Option.scala | 6 ++++-- test/files/neg/t4851.check | 4 ++-- test/files/run/t8549.scala | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 7282feebb692..39c583e63bc8 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -330,9 +330,11 @@ sealed abstract class Option[+A] extends Product with Serializable { * @version 1.0, 16/07/2003 */ @SerialVersionUID(1234815782226070388L) // value computed by serialver for 2.11.2, annotation added in 2.11.4 -final case class Some[+A](x: A) extends Option[A] { +final case class Some[+A](@deprecatedName('x, "2.12.0") value: A) extends Option[A] { def isEmpty = false - def get = x + def get = value + + @deprecated("Use .value instead.", "2.12.0") def x: A = value } diff --git a/test/files/neg/t4851.check b/test/files/neg/t4851.check index ac0854f8105c..721923e0ba3f 100644 --- a/test/files/neg/t4851.check +++ b/test/files/neg/t4851.check @@ -17,13 +17,13 @@ S.scala:4: warning: Adapting argument list by creating a 5-tuple: this may not b val x3 = new J(1, 2, 3, 4, 5) ^ S.scala:6: warning: Adapting argument list by creating a 3-tuple: this may not be what you want. - signature: Some.apply[A](x: A): Some[A] + signature: Some.apply[A](value: A): Some[A] given arguments: 1, 2, 3 after adaptation: Some((1, 2, 3): (Int, Int, Int)) val y1 = Some(1, 2, 3) ^ S.scala:7: warning: Adapting argument list by creating a 3-tuple: this may not be what you want. - signature: Some(x: A): Some[A] + signature: Some(value: A): Some[A] given arguments: 1, 2, 3 after adaptation: new Some((1, 2, 3): (Int, Int, Int)) val y2 = new Some(1, 2, 3) diff --git a/test/files/run/t8549.scala b/test/files/run/t8549.scala index f8d6819e33b0..da7a731459fd 100644 --- a/test/files/run/t8549.scala +++ b/test/files/run/t8549.scala @@ -79,10 +79,10 @@ object Test extends App { } } - // Generated on 20160706-15:44:41 with Scala version 2.12.0-20160629-163201-6612ba0) + // Generated on 20160715-08:27:53 with Scala version 2.12.0-20160715-012500-f5a80bd) overwrite.foreach(updateComment) - check(Some(1))("rO0ABXNyAApzY2FsYS5Tb21lESLyaV6hi3QCAAFMAAF4dAASTGphdmEvbGFuZy9PYmplY3Q7eHIADHNjYWxhLk9wdGlvbv5pN/3bDmZ0AgAAeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAQ==") + check(Some(1))("rO0ABXNyAApzY2FsYS5Tb21lESLyaV6hi3QCAAFMAAV2YWx1ZXQAEkxqYXZhL2xhbmcvT2JqZWN0O3hyAAxzY2FsYS5PcHRpb27+aTf92w5mdAIAAHhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAE=") check(None)("rO0ABXNyAAtzY2FsYS5Ob25lJEZQJPZTypSsAgAAeHIADHNjYWxhLk9wdGlvbv5pN/3bDmZ0AgAAeHA=") check(List(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5MaXN0JFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAABAwAAeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAgAAAAJzcQB+AAIAAAADc3IALHNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXJpYWxpemVFbmQkilxjW/dTC20CAAB4cHg=") @@ -181,10 +181,10 @@ object Test extends App { check(mutable.HashSet(1, 2, 3))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaFNldAAAAAAAAAABAwAAeHB3DQAAAcIAAAADAAAABQBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAgAAAAJzcQB+AAIAAAADeA==") check(mutable.TreeMap[Int, Int]())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcNx8qC229ZvwAgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZU1hcCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAABw") check(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcNx8qC229ZvwAgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZU1hcCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAAJzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSROb2RlGxHsFtValgACAAZaAANyZWRMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAARsZWZ0cQB+AAdMAAZwYXJlbnRxAH4AB0wABXJpZ2h0cQB+AAdMAAV2YWx1ZXEAfgAKeHAAc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFwcHNxAH4ACQFzcQB+AAwAAAADcHEAfgALcHNxAH4ADAAAAAZxAH4ADg==") - check(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcCRUcmVlTWFwVmlldx7MCZxLhVQ8AgADTAAGJG91dGVydAAiTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9UcmVlTWFwO0wABGZyb210AA5Mc2NhbGEvT3B0aW9uO0wABXVudGlscQB+AAJ4cgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVNYXDcfKgttvWb8AIAAkwACG9yZGVyaW5ndAAVTHNjYWxhL21hdGgvT3JkZXJpbmc7TAAmc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJFRyZWVNYXAkJHRyZWV0ACxMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1JlZEJsYWNrVHJlZSRUcmVlO3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JNmBnwaXZn6wAgAAeHBzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSRUcmVlAEynNPA1phUCAAJJAARzaXplTAAEcm9vdHQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJE5vZGU7eHAAAAACc3IAKnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5SZWRCbGFja1RyZWUkTm9kZRsR7BbVWpYAAgAGWgADcmVkTAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgAKTAAGcGFyZW50cQB+AApMAAVyaWdodHEAfgAKTAAFdmFsdWVxAH4ADXhwAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcHBzcQB+AAwBc3EAfgAPAAAAA3BxAH4ADnBzcQB+AA8AAAAGcQB+ABFzcQB+AANxAH4ACHEAfgALc3IACnNjYWxhLlNvbWURIvJpXqGLdAIAAUwAAXhxAH4ADXhyAAxzY2FsYS5PcHRpb27+aTf92w5mdAIAAHhwcQB+ABFzcQB+ABZzcQB+AA8AAAAC") + check(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZU1hcCRUcmVlTWFwVmlldx7MCZxLhVQ8AgADTAAGJG91dGVydAAiTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9UcmVlTWFwO0wABGZyb210AA5Mc2NhbGEvT3B0aW9uO0wABXVudGlscQB+AAJ4cgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVNYXDcfKgttvWb8AIAAkwACG9yZGVyaW5ndAAVTHNjYWxhL21hdGgvT3JkZXJpbmc7TAAmc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJFRyZWVNYXAkJHRyZWV0ACxMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1JlZEJsYWNrVHJlZSRUcmVlO3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JNmBnwaXZn6wAgAAeHBzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSRUcmVlAEynNPA1phUCAAJJAARzaXplTAAEcm9vdHQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJE5vZGU7eHAAAAACc3IAKnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5SZWRCbGFja1RyZWUkTm9kZRsR7BbVWpYAAgAGWgADcmVkTAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgAKTAAGcGFyZW50cQB+AApMAAVyaWdodHEAfgAKTAAFdmFsdWVxAH4ADXhwAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcHBzcQB+AAwBc3EAfgAPAAAAA3BxAH4ADnBzcQB+AA8AAAAGcQB+ABFzcQB+AANxAH4ACHEAfgALc3IACnNjYWxhLlNvbWURIvJpXqGLdAIAAUwABXZhbHVlcQB+AA14cgAMc2NhbGEuT3B0aW9u/mk3/dsOZnQCAAB4cHEAfgARc3EAfgAWc3EAfgAPAAAAAg==") check(mutable.TreeSet[Int]())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldM10nxFQDpt4AgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZVNldCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAABw") check(mutable.TreeSet(1, 3))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldM10nxFQDpt4AgACTAAIb3JkZXJpbmd0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMACZzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkVHJlZVNldCQkdHJlZXQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQk2YGfBpdmfrACAAB4cHNyACpzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWUATKc08DWmFQIAAkkABHNpemVMAARyb290dAAsTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9SZWRCbGFja1RyZWUkTm9kZTt4cAAAAAJzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSROb2RlGxHsFtValgACAAZaAANyZWRMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAARsZWZ0cQB+AAdMAAZwYXJlbnRxAH4AB0wABXJpZ2h0cQB+AAdMAAV2YWx1ZXEAfgAKeHAAc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFwcHNxAH4ACQFzcQB+AAwAAAADcHEAfgALcHBw") - check(mutable.TreeSet(1, 3).range(1, 2))( "rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldCRUcmVlU2V0Vmlld2JdAzqy0DpGAgADTAAGJG91dGVydAAiTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9UcmVlU2V0O0wABGZyb210AA5Mc2NhbGEvT3B0aW9uO0wABXVudGlscQB+AAJ4cgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXTNdJ8RUA6beAIAAkwACG9yZGVyaW5ndAAVTHNjYWxhL21hdGgvT3JkZXJpbmc7TAAmc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJFRyZWVTZXQkJHRyZWV0ACxMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1JlZEJsYWNrVHJlZSRUcmVlO3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JNmBnwaXZn6wAgAAeHBzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSRUcmVlAEynNPA1phUCAAJJAARzaXplTAAEcm9vdHQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJE5vZGU7eHAAAAACc3IAKnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5SZWRCbGFja1RyZWUkTm9kZRsR7BbVWpYAAgAGWgADcmVkTAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgAKTAAGcGFyZW50cQB+AApMAAVyaWdodHEAfgAKTAAFdmFsdWVxAH4ADXhwAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcHBzcQB+AAwBc3EAfgAPAAAAA3BxAH4ADnBwcHNxAH4AA3EAfgAIcQB+AAtzcgAKc2NhbGEuU29tZREi8mleoYt0AgABTAABeHEAfgANeHIADHNjYWxhLk9wdGlvbv5pN/3bDmZ0AgAAeHBxAH4AEXNxAH4AFXNxAH4ADwAAAAI=") + check(mutable.TreeSet(1, 3).range(1, 2))( "rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuVHJlZVNldCRUcmVlU2V0Vmlld2JdAzqy0DpGAgADTAAGJG91dGVydAAiTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9UcmVlU2V0O0wABGZyb210AA5Mc2NhbGEvT3B0aW9uO0wABXVudGlscQB+AAJ4cgAgc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXTNdJ8RUA6beAIAAkwACG9yZGVyaW5ndAAVTHNjYWxhL21hdGgvT3JkZXJpbmc7TAAmc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJFRyZWVTZXQkJHRyZWV0ACxMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1JlZEJsYWNrVHJlZSRUcmVlO3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JNmBnwaXZn6wAgAAeHBzcgAqc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlJlZEJsYWNrVHJlZSRUcmVlAEynNPA1phUCAAJJAARzaXplTAAEcm9vdHQALExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUmVkQmxhY2tUcmVlJE5vZGU7eHAAAAACc3IAKnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5SZWRCbGFja1RyZWUkTm9kZRsR7BbVWpYAAgAGWgADcmVkTAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgAKTAAGcGFyZW50cQB+AApMAAVyaWdodHEAfgAKTAAFdmFsdWVxAH4ADXhwAHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcHBzcQB+AAwBc3EAfgAPAAAAA3BxAH4ADnBwcHNxAH4AA3EAfgAIcQB+AAtzcgAKc2NhbGEuU29tZREi8mleoYt0AgABTAAFdmFsdWVxAH4ADXhyAAxzY2FsYS5PcHRpb27+aTf92w5mdAIAAHhwcQB+ABFzcQB+ABVzcQB+AA8AAAAC") // TODO SI-8576 Uninitialized field under -Xcheckinit // check(new mutable.History())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGlzdG9yeUhuXxDIFJrsAgACSQAKbWF4SGlzdG9yeUwAA2xvZ3QAIExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUXVldWU7eHAAAAPoc3IAHnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5RdWV1ZbjMURVfOuHHAgAAeHIAJHNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5NdXRhYmxlTGlzdFJpnjJ+gFbAAgADSQADbGVuTAAGZmlyc3QwdAAlTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9MaW5rZWRMaXN0O0wABWxhc3QwcQB+AAV4cAAAAABzcgAjc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZExpc3Sak+nGCZHaUQIAAkwABGVsZW10ABJMamF2YS9sYW5nL09iamVjdDtMAARuZXh0dAAeTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9TZXE7eHBwcQB+AApxAH4ACg==") check(mutable.LinkedHashMap(1 -> 2))( "rO0ABXNyACZzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuTGlua2VkSGFzaE1hcAAAAAAAAAABAwAAeHB3DQAAAu4AAAABAAAABABzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAgAAAAJ4") From 543d719dce062e6ea99c21c7320def711af1cf9e Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Mon, 25 Apr 2016 15:00:09 -0700 Subject: [PATCH 135/153] Retain javadoc comments in scaladoc * Hook into java parser to generate doc comments * Generate empty trees for java implementation bodies --- src/compiler/scala/tools/nsc/Global.scala | 4 +- .../tools/nsc/ast/parser/SyntaxAnalyzer.scala | 2 +- .../scala/tools/nsc/javac/JavaParsers.scala | 15 ++- .../scala/tools/nsc/javac/JavaScanners.scala | 38 +++--- .../scala/tools/nsc/typechecker/Typers.scala | 7 +- .../tools/nsc/doc/ScaladocAnalyzer.scala | 119 +++++++++++------- .../scala/tools/nsc/doc/ScaladocGlobal.scala | 3 + .../tools/partest/ScaladocModelTest.scala | 2 +- test/files/run/t5699.check | 4 +- test/scaladoc/resources/SI-4826.java | 20 +++ test/scaladoc/run/SI-4826.check | 1 + test/scaladoc/run/SI-4826.scala | 30 +++++ 12 files changed, 171 insertions(+), 74 deletions(-) create mode 100644 test/scaladoc/resources/SI-4826.java create mode 100644 test/scaladoc/run/SI-4826.check create mode 100644 test/scaladoc/run/SI-4826.scala diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 9d6693c00fd8..d4c2896c5c65 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -411,7 +411,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) override val initial = true } - import syntaxAnalyzer.{ UnitScanner, UnitParser } + import syntaxAnalyzer.{ UnitScanner, UnitParser, JavaUnitParser } // !!! I think we're overdue for all these phase objects being lazy vals. // There's no way for a Global subclass to provide a custom typer @@ -1042,6 +1042,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def newUnitParser(code: String, filename: String = ""): UnitParser = newUnitParser(newCompilationUnit(code, filename)) + def newJavaUnitParser(unit: CompilationUnit): JavaUnitParser = new JavaUnitParser(unit) + /** A Run is a single execution of the compiler on a set of units. */ class Run extends RunContextApi with RunReporting with RunParsing { diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala index df2073785b84..e0667b5a3ebb 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala @@ -82,7 +82,7 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse } private def initialUnitBody(unit: CompilationUnit): Tree = { - if (unit.isJava) new JavaUnitParser(unit).parse() + if (unit.isJava) newJavaUnitParser(unit).parse() else if (currentRun.parsing.incompleteHandled) newUnitParser(unit).parse() else newUnitParser(unit).smartParse() } diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index fd9c99a3b966..01ca8033accd 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -111,7 +111,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { def arrayOf(tpt: Tree) = AppliedTypeTree(scalaDot(tpnme.Array), List(tpt)) - def blankExpr = Ident(nme.WILDCARD) + def blankExpr = EmptyTree def makePackaging(pkg: RefTree, stats: List[Tree]): PackageDef = atPos(pkg.pos) { PackageDef(pkg, stats) } @@ -135,6 +135,11 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { DefDef(Modifiers(Flags.JAVA), nme.CONSTRUCTOR, List(), List(vparams), TypeTree(), blankExpr) } + /** A hook for joining the comment associated with a definition. + * Overridden by scaladoc. + */ + def joinComment(trees: => List[Tree]): List[Tree] = trees + // ------------- general parsing --------------------------- /** skip parent or brace enclosed sequence of things */ @@ -581,7 +586,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { case CLASS | ENUM | INTERFACE | AT => typeDecl(if (definesInterface(parentToken)) mods | Flags.STATIC else mods) case _ => - termDecl(mods, parentToken) + joinComment(termDecl(mods, parentToken)) } def makeCompanionObject(cdef: ClassDef, statics: List[Tree]): Tree = @@ -833,10 +838,10 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { } def typeDecl(mods: Modifiers): List[Tree] = in.token match { - case ENUM => enumDecl(mods) - case INTERFACE => interfaceDecl(mods) + case ENUM => joinComment(enumDecl(mods)) + case INTERFACE => joinComment(interfaceDecl(mods)) case AT => annotationDecl(mods) - case CLASS => classDecl(mods) + case CLASS => joinComment(classDecl(mods)) case _ => in.nextToken(); syntaxError("illegal start of type declaration", skipIt = true); List(errorTypeTree) } diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index c74a6938c6dd..e11ac9404162 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -577,21 +577,29 @@ trait JavaScanners extends ast.parser.ScannersCommon { } } - protected def skipComment(): Boolean = { - @tailrec def skipLineComment(): Unit = in.ch match { - case CR | LF | SU => - case _ => in.next; skipLineComment() - } - @tailrec def skipJavaComment(): Unit = in.ch match { - case SU => incompleteInputError("unclosed comment") - case '*' => in.next; if (in.ch == '/') in.next else skipJavaComment() - case _ => in.next; skipJavaComment() - } - in.ch match { - case '/' => in.next ; skipLineComment() ; true - case '*' => in.next ; skipJavaComment() ; true - case _ => false - } + protected def putCommentChar(): Unit = in.next() + + protected def skipBlockComment(isDoc: Boolean): Unit = in.ch match { + case SU => incompleteInputError("unclosed comment") + case '*' => putCommentChar() ; if (in.ch == '/') putCommentChar() else skipBlockComment(isDoc) + case _ => putCommentChar() ; skipBlockComment(isDoc) + } + + protected def skipLineComment(): Unit = in.ch match { + case CR | LF | SU => + case _ => putCommentChar() ; skipLineComment() + } + + protected def skipComment(): Boolean = in.ch match { + case '/' => putCommentChar() ; skipLineComment() ; true + case '*' => + putCommentChar() + in.ch match { + case '*' => skipBlockComment(isDoc = true) + case _ => skipBlockComment(isDoc = false) + } + true + case _ => false } // Identifiers --------------------------------------------------------------- diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9fa3564b2bab..ba104fb7a6b1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2247,9 +2247,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe) } - if (meth.isClassConstructor && !isPastTyper && !meth.owner.isSubClass(AnyValClass)) { - // At this point in AnyVal there is no supercall, which will blow up - // in computeParamAliases; there's nothing to be computed for Anyval anyway. + if (meth.isClassConstructor && !isPastTyper && !meth.owner.isSubClass(AnyValClass) && !meth.isJava) { + // There are no supercalls for AnyVal or constructors from Java sources, which + // would blow up in computeParamAliases; there's nothing to be computed for them + // anyway. if (meth.isPrimaryConstructor) computeParamAliases(meth.owner, vparamss1, rhs1) else diff --git a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala index 8ea8c4deff82..2152ce234a78 100644 --- a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala +++ b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala @@ -101,52 +101,6 @@ trait ScaladocAnalyzer extends Analyzer { abstract class ScaladocSyntaxAnalyzer[G <: Global](val global: G) extends SyntaxAnalyzer { import global._ - class ScaladocJavaUnitParser(unit: CompilationUnit) extends { - override val in = new ScaladocJavaUnitScanner(unit) - } with JavaUnitParser(unit) { } - - class ScaladocJavaUnitScanner(unit: CompilationUnit) extends JavaUnitScanner(unit) { - /** buffer for the documentation comment - */ - var docBuffer: StringBuilder = null - - /** add the given character to the documentation buffer - */ - protected def putDocChar(c: Char) { - if (docBuffer ne null) docBuffer.append(c) - } - - override protected def skipComment(): Boolean = { - if (in.ch == '/') { - do { - in.next - } while ((in.ch != CR) && (in.ch != LF) && (in.ch != SU)) - true - } else if (in.ch == '*') { - docBuffer = null - in.next - val scaladoc = ("/**", "*/") - if (in.ch == '*') - docBuffer = new StringBuilder(scaladoc._1) - do { - do { - if (in.ch != '*' && in.ch != SU) { - in.next; putDocChar(in.ch) - } - } while (in.ch != '*' && in.ch != SU) - while (in.ch == '*') { - in.next; putDocChar(in.ch) - } - } while (in.ch != '/' && in.ch != SU) - if (in.ch == '/') in.next - else incompleteInputError("unclosed comment") - true - } else { - false - } - } - } - class ScaladocUnitScanner(unit0: CompilationUnit, patches0: List[BracePatch]) extends UnitScanner(unit0, patches0) { private var docBuffer: StringBuilder = null // buffer for comments (non-null while scanning) @@ -259,4 +213,77 @@ abstract class ScaladocSyntaxAnalyzer[G <: Global](val global: G) extends Syntax else trees } } + + class ScaladocJavaUnitScanner(unit: CompilationUnit) extends JavaUnitScanner(unit) { + + private val docBuffer: StringBuilder = new StringBuilder + private var inDocComment = false + private var docStart: Int = 0 + private var lastDoc: DocComment = null + + // get last doc comment + def flushDoc(): DocComment = try lastDoc finally lastDoc = null + + override protected def putCommentChar(): Unit = { + if (inDocComment) docBuffer append in.ch + in.next + } + + override protected def skipBlockComment(isDoc: Boolean): Unit = { + // condition is true when comment is entered the first time, + // i.e. immediately after "/*" and when current character is "*" + if (!inDocComment && isDoc) { + docBuffer append "/*" + docStart = currentPos.start + inDocComment = true + } + super.skipBlockComment(isDoc) + } + + override protected def skipComment(): Boolean = { + val skipped = super.skipComment() + if (skipped && inDocComment) { + val raw = docBuffer.toString + val position = Position.range(unit.source, docStart, docStart, in.cpos) + lastDoc = DocComment(raw, position) + signalParsedDocComment(raw, position) + docBuffer.setLength(0) // clear buffer + inDocComment = false + true + } else { + skipped + } + } + + } + + class ScaladocJavaUnitParser(unit: CompilationUnit) extends { + override val in = new ScaladocJavaUnitScanner(unit) + } with JavaUnitParser(unit) { + + override def joinComment(trees: => List[Tree]): List[Tree] = { + val doc = in.flushDoc() + + if ((doc ne null) && doc.raw.length > 0) { + log(s"joinComment(doc=$doc)") + val joined = trees map { t => + DocDef(doc, t) setPos { + if (t.pos.isDefined) { + val pos = doc.pos.withEnd(t.pos.end) + pos.makeTransparent + } else { + t.pos + } + } + } + joined.find(_.pos.isOpaqueRange) foreach { main => + val mains = List(main) + joined foreach { t => if (t ne main) ensureNonOverlapping(t, mains) } + } + joined + } else { + trees + } + } + } } diff --git a/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala b/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala index 10bfe6f94ba8..625d074df5b0 100644 --- a/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala +++ b/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala @@ -13,6 +13,7 @@ trait ScaladocGlobalTrait extends Global { override val useOffsetPositions = false override def newUnitParser(unit: CompilationUnit) = new syntaxAnalyzer.ScaladocUnitParser(unit, Nil) + override def newJavaUnitParser(unit: CompilationUnit) = new syntaxAnalyzer.ScaladocJavaUnitParser(unit) override lazy val syntaxAnalyzer = new ScaladocSyntaxAnalyzer[outer.type](outer) { val runsAfter = List[String]() @@ -40,6 +41,8 @@ class ScaladocGlobal(settings: doc.Settings, reporter: Reporter) extends Global( phasesSet += analyzer.typerFactory } override def forScaladoc = true + override def createJavadoc = true + override lazy val analyzer = new { val global: ScaladocGlobal.this.type = ScaladocGlobal.this } with ScaladocAnalyzer diff --git a/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala b/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala index 1ad3b3ff2bf9..44c1146a1457 100644 --- a/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala +++ b/src/scaladoc/scala/tools/partest/ScaladocModelTest.scala @@ -81,7 +81,7 @@ abstract class ScaladocModelTest extends DirectTest { private[this] var settings: doc.Settings = null // create a new scaladoc compiler - private[this] def newDocFactory: DocFactory = { + def newDocFactory: DocFactory = { settings = new doc.Settings(_ => ()) settings.scaladocQuietRun = true // yaay, no more "model contains X documentable templates"! val args = extraSettings + " " + scaladocSettings diff --git a/test/files/run/t5699.check b/test/files/run/t5699.check index df19644ae618..8d19ecd321c5 100644 --- a/test/files/run/t5699.check +++ b/test/files/run/t5699.check @@ -1,10 +1,10 @@ [[syntax trees at end of parser]] // annodef.java package { object MyAnnotation extends { - def () = _ + def () }; class MyAnnotation extends scala.annotation.Annotation with _root_.java.lang.annotation.Annotation with scala.annotation.ClassfileAnnotation { - def () = _; + def (); def value(): String } } diff --git a/test/scaladoc/resources/SI-4826.java b/test/scaladoc/resources/SI-4826.java new file mode 100644 index 000000000000..f735ce633515 --- /dev/null +++ b/test/scaladoc/resources/SI-4826.java @@ -0,0 +1,20 @@ +package test.scaladoc; + +/** + * Testing java comments. The presence of a :marker: + * tag is verified by tests. + */ +public class JavaComments { + + /** + * Compute the answer to the ultimate question of life, the + * universe, and everything. :marker: + * @param factor scaling factor to the answer + * @return the answer to everything (42) scaled by factor + */ + public int answer(int factor) { + return 42 * factor; + } + +} + diff --git a/test/scaladoc/run/SI-4826.check b/test/scaladoc/run/SI-4826.check new file mode 100644 index 000000000000..619c56180bb9 --- /dev/null +++ b/test/scaladoc/run/SI-4826.check @@ -0,0 +1 @@ +Done. diff --git a/test/scaladoc/run/SI-4826.scala b/test/scaladoc/run/SI-4826.scala new file mode 100644 index 000000000000..50e446800287 --- /dev/null +++ b/test/scaladoc/run/SI-4826.scala @@ -0,0 +1,30 @@ +import scala.tools.nsc.doc.Universe +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest + +object Test extends ScaladocModelTest { + + override def resourceFile = "SI-4826.java" + + // overridden to pass explicit files to newDocFactory.makeUniverse (rather than code strings) + // since the .java file extension is required + override def model: Option[Universe] = { + val path = resourcePath + "/" + resourceFile + newDocFactory.makeUniverse(Left(List(path))) + } + + // no need for special settings + def scaladocSettings = "" + + def testModel(rootPackage: Package) = { + import access._ + val Tag = ":marker:" + + val base = rootPackage._package("test")._package("scaladoc") + val clazz = base._class("JavaComments") + val method = clazz._method("answer") + + assert(extractCommentText(clazz.comment.get).contains(Tag)) + assert(extractCommentText(method.comment.get).contains(Tag)) + } +} From 36e2ae2fbd3d3637f2be6453e67778b706e1baa9 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Mon, 11 Jul 2016 15:55:19 +0200 Subject: [PATCH 136/153] Switch the bootstrap build over to sbt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All of the individual ant builds that occured during `bootstrap` are replaced by equivalent sbt builds. - Allow extra dashes in version suffix when using SPLIT - Clean up ScriptCommands - Building an extra `locker` for stability testing with ant was not necessary but sbt also drops `strap`, so we need to build again with `quick` to get the equivalent of `strap`. The script for checking stability is invoked directly from the bootstrap script, not from sbt. - `STARR` and `locker` build output is still logged to `logs/builds`, the main build runs log directly to the main console with colored output. - Allow `—show-log` option on partest command line in sbt - Normalize inferred LUB in `run/t7747-repl.scala` - Add `normalize` feature from `ReplTest` to `InteractiveTest` - Normalize inferred LUBs in `presentation/callcc-interpreter` --- project/PartestUtil.scala | 2 +- project/ScriptCommands.scala | 124 +++++++++++++++--- project/VersionUtil.scala | 2 +- scripts/jobs/integrate/bootstrap | 72 +++++----- scripts/jobs/validate/test | 11 +- .../interactive/tests/InteractiveTest.scala | 10 +- .../callcc-interpreter/Runner.scala | 5 +- test/files/run/t7747-repl.scala | 8 +- 8 files changed, 164 insertions(+), 70 deletions(-) diff --git a/project/PartestUtil.scala b/project/PartestUtil.scala index 8793e9c0a55d..99b978515caf 100644 --- a/project/PartestUtil.scala +++ b/project/PartestUtil.scala @@ -29,7 +29,7 @@ object PartestUtil { val knownUnaryOptions = List( "--pos", "--neg", "--run", "--jvm", "--res", "--ant", "--scalap", "--specialized", "--scalacheck", "--instrumented", "--presentation", "--failed", "--update-check", - "--show-diff", "--verbose", "--terse", "--debug", "--version", "--self-test", "--help") + "--show-diff", "--show-log", "--verbose", "--terse", "--debug", "--version", "--self-test", "--help") val srcPathOption = "--srcpath" val grepOption = "--grep" diff --git a/project/ScriptCommands.scala b/project/ScriptCommands.scala index 0bf43b18e872..accbadbbf66c 100644 --- a/project/ScriptCommands.scala +++ b/project/ScriptCommands.scala @@ -4,30 +4,116 @@ import BuildSettings.autoImport._ /** Custom commands for use by the Jenkins scripts. This keeps the surface area and call syntax small. */ object ScriptCommands { - def all = Seq(setupPublishCore, setupValidateTest) + def all = Seq( + setupPublishCore, + setupValidateTest, + setupBootstrapStarr, setupBootstrapLocker, setupBootstrapQuick, setupBootstrapPublish, + testAll + ) /** Set up the environment for `validate/publish-core`. The argument is the Artifactory snapshot repository URL. */ - def setupPublishCore = Command.single("setupPublishCore") { case (state, url) => - Project.extract(state).append(Seq( - baseVersionSuffix in Global := "SHA-SNAPSHOT", - // Append build.timestamp to Artifactory URL to get consistent build numbers (see https://github.com/sbt/sbt/issues/2088): - publishTo in Global := Some("scala-pr" at url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis), - publishArtifact in (Compile, packageDoc) in ThisBuild := false, - scalacOptions in Compile in ThisBuild += "-opt:l:classpath", - logLevel in ThisBuild := Level.Info, - logLevel in update in ThisBuild := Level.Warn - ), state) - } + def setupPublishCore = setup("setupPublishCore") { case Seq(url) => + Seq( + baseVersionSuffix in Global := "SHA-SNAPSHOT" + ) ++ publishTarget(url) ++ noDocs ++ enableOptimizer + } /** Set up the environment for `validate/test`. The argument is the Artifactory snapshot repository URL. */ - def setupValidateTest = Command.single("setupValidateTest") { case (state, url) => + def setupValidateTest = setup("setupValidateTest") { case Seq(url) => //TODO When ant is gone, pass starr version as an argument to this command instead of using version.properties - Project.extract(state).append(Seq( + Seq( + resolvers in Global += "scala-pr" at url, + testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff")) + ) ++ enableOptimizer + } + + /** Set up the environment for building STARR in `validate/bootstrap`. The arguments are: + * - Repository URL for publishing + * - Version number to publish */ + def setupBootstrapStarr = setup("setupBootstrapStarr") { case Seq(url, ver) => + Seq( + baseVersion in Global := ver, + baseVersionSuffix in Global := "SPLIT" + ) ++ publishTarget(url) ++ noDocs ++ enableOptimizer + } + + /** Set up the environment for building locker in `validate/bootstrap`. The arguments are: + * - Repository URL for publishing locker and resolving STARR + * - Version number to publish */ + def setupBootstrapLocker = setup("setupBootstrapLocker") { case Seq(url, ver) => + Seq( + baseVersion in Global := ver, + baseVersionSuffix in Global := "SPLIT", + resolvers in Global += "scala-pr" at url + ) ++ publishTarget(url) ++ noDocs ++ enableOptimizer + } + + /** Set up the environment for building quick in `validate/bootstrap`. The arguments are: + * - Repository URL for publishing + * - Version number to publish */ + def setupBootstrapQuick = setup("setupBootstrapQuick") { case Seq(url, ver) => + Seq( + baseVersion in Global := ver, + baseVersionSuffix in Global := "SPLIT", + resolvers in Global += "scala-pr" at url, + testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff")) + ) ++ publishTarget(url) ++ enableOptimizer + } + + /** Set up the environment for publishing in `validate/bootstrap`. The arguments are: + * - Temporary bootstrap repository URL for resolving modules + * - Version number to publish + * All artifacts are published to Sonatype. GPG signing has to be configured from the + * shell script after `setupBootstrapPublish` because we don't pull the GPG plugin in + * by default, so we cannot reference its keys statically. */ + def setupBootstrapPublish = setup("setupBootstrapPublish") { case Seq(url, ver) => + // Define a copy of the setting key here in case the plugin is not part of the build + val pgpPassphrase = SettingKey[Option[Array[Char]]]("pgp-passphrase", "The passphrase associated with the secret used to sign artifacts.", KeyRanks.BSetting) + Seq( + baseVersion in Global := ver, + baseVersionSuffix in Global := "SPLIT", resolvers in Global += "scala-pr" at url, - scalacOptions in Compile in ThisBuild += "-opt:l:classpath", - testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff")), - logLevel in ThisBuild := Level.Info, - logLevel in update in ThisBuild := Level.Warn - ), state) + publishTo in Global := Some("sonatype-releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2"), + credentials in Global += Credentials(Path.userHome / ".credentials-sonatype"), + pgpPassphrase in Global := Some(Array.empty) + ) ++ enableOptimizer + } + + private[this] def setup(name: String)(f: Seq[String] => Seq[Setting[_]]) = + Command.args(name, name) { case (state, seq) => Project.extract(state).append(f(seq) ++ resetLogLevels, state) } + + private[this] val resetLogLevels = Seq( + logLevel in ThisBuild := Level.Info, + logLevel in update in ThisBuild := Level.Warn + ) + + private[this] val enableOptimizer = Seq( + scalacOptions in Compile in ThisBuild += "-opt:l:classpath" + ) + + private[this] val noDocs = Seq( + publishArtifact in (Compile, packageDoc) in ThisBuild := false + ) + + private[this] def publishTarget(url: String) = Seq( + // Append build.timestamp to Artifactory URL to get consistent build numbers (see https://github.com/sbt/sbt/issues/2088): + publishTo in Global := Some("scala-pr-publish" at url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis) + ) + + def testAll = Command.command("testAll") { state => + val cmds = Seq( + "test", + "partest run pos neg jvm", + "partest res scalap specialized scalacheck", + "partest instrumented presentation", + "partest --srcpath scaladoc", + "osgiTestFelix/test", + "osgiTestEclipse/test", + "library/mima", + "reflect/mima", + "doc" + ) + state.log.info(cmds.mkString("Running all tests: \"", "\", \"", "\"")) + cmds ::: state } } diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala index 4705bbb6ce36..148fdfbc2343 100644 --- a/project/VersionUtil.scala +++ b/project/VersionUtil.scala @@ -61,7 +61,7 @@ object VersionUtil { val (base, suffix) = { val (b, s) = (baseVersion.value, baseVersionSuffix.value) if(s == "SPLIT") { - val split = """([\w+\.]+)(-[\w+\.]+)??""".r + val split = """([\w+\.]+)(-[\w+\.-]+)??""".r val split(b2, sOrNull) = b (b2, Option(sOrNull).map(_.drop(1)).getOrElse("")) } else (b, s) diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index 7716dc9eb1c1..bdc50323a8c6 100644 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -92,7 +92,7 @@ publishLockerPrivateTask=${publishLockerPrivateTask-$publishPrivateTask} # set t forceRebuild=${forceRebuild-no} -antBuildTask="${antBuildTask-nightly}" # TESTING leave empty to avoid the sanity check (don't set it to "init" because ant will croak) +sbtBuildTask="testAll" # TESTING leave empty to avoid the sanity check clean="clean" # TESTING leave empty to speed up testing baseDir=${WORKSPACE-`pwd`} @@ -174,11 +174,11 @@ function st_stagingRepoClose() { # the old version (on jenkins, and I don't want to upgrade for risk of breaking other builds) honors -sbt-dir # the new version of sbt-extras ignores sbt-dir, so we pass it in as -Dsbt.global.base # need to set sbt-dir to one that has the gpg.sbt plugin config -sbtArgs="-no-colors -ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$sbtRepositoryConfig -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13" +sbtArgs="-ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$sbtRepositoryConfig -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13" sbtBuild() { - echo "### sbtBuild: "$SBT_CMD $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@" - $SBT_CMD $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@" >> $baseDir/logs/builds 2>&1 + echo "### sbtBuild: "$SBT_CMD -no-colors $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@" + $SBT_CMD -no-colors $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@" >> $baseDir/logs/builds 2>&1 } sbtResolve() { @@ -186,8 +186,8 @@ sbtResolve() { touch build.sbt # Can be set to `full` if a module requires cross-versioning against the full Scala version, like the continuations plugin used to. cross=${4-binary} - echo "### sbtResolve: $SBT_CMD $sbtArgs " "${scalaVersionTasks[@]}" "\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross" - $SBT_CMD $sbtArgs "${scalaVersionTasks[@]}" \ + echo "### sbtResolve: $SBT_CMD -no-colors $sbtArgs " "${scalaVersionTasks[@]}" "\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross" + $SBT_CMD -no-colors $sbtArgs "${scalaVersionTasks[@]}" \ "set libraryDependencies := Seq(\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross)" \ 'show update' >> $baseDir/logs/resolution 2>&1 } @@ -490,13 +490,7 @@ bootstrap() { git clone --reference $WORKSPACE/.git $WORKSPACE/.git $STARR_DIR cd $STARR_DIR git co $STARR_REF - ant -Dmaven.version.number=$STARR_VER\ - -Dremote.snapshot.repository=NOPE\ - -Dremote.release.repository=$releaseTempRepoUrl\ - -Drepository.credentials.id=$releaseTempRepoCred\ - -Ddocs.skip=1\ - -Dlocker.skip=1\ - $publishStarrPrivateTask >> $baseDir/logs/builds 2>&1 + $SBT_CMD -no-colors $sbtArgs --warn "setupBootstrapStarr $releaseTempRepoUrl $STARR_VER" $clean publish >> $baseDir/logs/builds 2>&1 ) fi @@ -510,14 +504,7 @@ bootstrap() { # publish more than just core: partest needs scalap # in sabbus lingo, the resulting Scala build will be used as starr to build the released Scala compiler if [ ! -z "$STARR_VER" ]; then SET_STARR=-Dstarr.version=$STARR_VER; fi - ant -Dmaven.version.number=$SCALA_VER\ - -Dremote.snapshot.repository=NOPE\ - $SET_STARR\ - -Dremote.release.repository=$releaseTempRepoUrl\ - -Drepository.credentials.id=$releaseTempRepoCred\ - -Ddocs.skip=1\ - -Dlocker.skip=1\ - $publishLockerPrivateTask >> $baseDir/logs/builds 2>&1 + $SBT_CMD -no-colors $sbtArgs $SET_STARR --warn "setupBootstrapLocker $releaseTempRepoUrl $SCALA_VER" $clean publish >> $baseDir/logs/builds 2>&1 echo "### Building modules using locker" @@ -534,7 +521,7 @@ bootstrap() { echo "### Bootstrapping Scala using locker" # # TODO: close all open staging repos so that we can be reasonably sure the only open one we see after publishing below is ours - # # the ant call will create a new one + # # the sbt call will create a new one # # Rebuild Scala with these modules so that all binary versions are consistent. # Update versions.properties to new modules. @@ -542,23 +529,35 @@ bootstrap() { # don't skip locker (-Dlocker.skip=1), or stability will fail # overwrite "locker" version of scala at private-repo with bootstrapped version cd $baseDir - rm -rf build/ # must leave everything else in $baseDir for downstream jobs + rm -rf build/ - ant -Dstarr.version=$SCALA_VER\ - -Dextra.repo.url=$releaseTempRepoUrl\ - -Dmaven.version.suffix=$SCALA_VER_SUFFIX\ + $SBT_CMD $sbtArgs \ + --warn \ + -Dstarr.version=$SCALA_VER \ ${updatedModuleVersions[@]} \ - -Dupdate.versions=1\ - -Dscaladoc.git.commit=$SCALADOC_SOURCE_LINKS_VER\ - -Dremote.snapshot.repository=NOPE\ - -Dremote.release.repository=$releaseTempRepoUrl\ - -Drepository.credentials.id=$releaseTempRepoCred\ - -Dscalac.args.optimise=-opt:l:classpath\ - $antBuildTask $publishPrivateTask + "setupBootstrapQuick $releaseTempRepoUrl $SCALA_VER" \ + $clean \ + $sbtBuildTask \ + dist/mkQuick \ + publish | grep -v "was too long to be displayed in the webview, and will be left out" # clear ivy cache (and to be sure, local as well), so the next round of sbt builds sees the fresh scala rm -rf $baseDir/ivy2 + # Run stability tests using the just built version as "quick" and a new version as "strap" + mv build/quick quick1 + rm -rf build/ + $SBT_CMD $sbtArgs \ + --warn \ + -Dstarr.version=$SCALA_VER \ + ${updatedModuleVersions[@]} \ + "setupBootstrapQuick $releaseTempRepoUrl $SCALA_VER" \ + $clean \ + dist/mkQuick + mv build/quick build/strap + mv quick1 build/quick + tools/stability-test.sh + # TODO: create PR with following commit (note that release will have been tagged already) # git commit versions.properties -m"Bump versions.properties for $SCALA_VER." } @@ -571,7 +570,12 @@ publishSonatype() { # stage to sonatype, along with all modules -Dmaven.version.suffix/-Dbuild.release not necessary, # since we're just publishing an existing build echo "### Publishing core to sonatype" - ant -Dmaven.version.number=$SCALA_VER $publishSonatypeTaskCore + $SBT_CMD $sbtArgs \ + --warn \ + -Dstarr.version=$SCALA_VER \ + ${updatedModuleVersions[@]} \ + "setupBootstrapPublish $releaseTempRepoUrl $SCALA_VER" \ + publishSigned | grep -v "was too long to be displayed in the webview, and will be left out" echo "### Publishing modules to sonatype" # build/test/publish scala core modules to sonatype (this will start a new staging repo) diff --git a/scripts/jobs/validate/test b/scripts/jobs/validate/test index 3cd8af56081b..dd36c5db18ce 100755 --- a/scripts/jobs/validate/test +++ b/scripts/jobs/validate/test @@ -20,16 +20,7 @@ case $prDryRun in --warn \ "setupValidateTest $prRepoUrl" \ $testExtraArgs \ - "test" \ - "partest run pos neg jvm" \ - "partest res scalap specialized scalacheck" \ - "partest instrumented presentation" \ - "partest --srcpath scaladoc" \ - osgiTestFelix/test \ - osgiTestEclipse/test \ - library/mima \ - reflect/mima \ - doc + testAll ;; diff --git a/src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala index 2cb4f5fd4a39..00096dd359d8 100644 --- a/src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala +++ b/src/interactive/scala/tools/nsc/interactive/tests/InteractiveTest.scala @@ -78,10 +78,16 @@ abstract class InteractiveTest } protected def execute(): Unit = { - loadSources() - runDefaultTests() + util.stringFromStream { ostream => + Console.withOut(ostream) { + loadSources() + runDefaultTests() + } + }.lines.map(normalize).foreach(println) } + protected def normalize(s: String) = s + /** Load all sources before executing the test. */ protected def loadSources() { // ask the presentation compiler to track all sources. We do diff --git a/test/files/presentation/callcc-interpreter/Runner.scala b/test/files/presentation/callcc-interpreter/Runner.scala index 1ef3cf902531..a5698be5c27e 100644 --- a/test/files/presentation/callcc-interpreter/Runner.scala +++ b/test/files/presentation/callcc-interpreter/Runner.scala @@ -1,3 +1,6 @@ import scala.tools.nsc.interactive.tests._ -object Test extends InteractiveTest \ No newline at end of file +object Test extends InteractiveTest { + // Normalize ordering of LUB + override def normalize(s: String) = s.replace("Serializable with Product", "Product with Serializable") +} diff --git a/test/files/run/t7747-repl.scala b/test/files/run/t7747-repl.scala index c6a7e419aa14..0094d3ba98e1 100644 --- a/test/files/run/t7747-repl.scala +++ b/test/files/run/t7747-repl.scala @@ -8,8 +8,12 @@ object Test extends ReplTest { s } - // replace indylambda function names by - override def normalize(s: String) = """\$Lambda.*""".r.replaceAllIn(s, "") + override def normalize(s: String) = { + // replace indylambda function names by + val s2 = """\$Lambda.*""".r.replaceAllIn(s, "") + // Normalize ordering of LUB + s2.replace("Serializable with Product", "Product with Serializable") + } def code = """ |var x = 10 From 11688eb95b88f02c89c5974c3ce22290b57a5374 Mon Sep 17 00:00:00 2001 From: Christopher Davenport Date: Fri, 15 Jul 2016 16:41:39 -0400 Subject: [PATCH 137/153] SI-9691 BufferedIterator should expose a headOption This exposes a new API to the BufferedIterator trait. It will return the next element of an iterator as an Option. The return will be Some(value) if there is a next value, and None if there is not a next element. --- .../scala/collection/BufferedIterator.scala | 6 ++++ .../junit/scala/collection/IteratorTest.scala | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/library/scala/collection/BufferedIterator.scala b/src/library/scala/collection/BufferedIterator.scala index e6e97d584cb3..1424ef2fd049 100644 --- a/src/library/scala/collection/BufferedIterator.scala +++ b/src/library/scala/collection/BufferedIterator.scala @@ -24,5 +24,11 @@ trait BufferedIterator[+A] extends Iterator[A] { */ def head: A + /** Returns an option of the next element of an iterator without advancing beyond it. + * @return the next element of this iterator if it has a next element + * `None` if it does not + */ + def headOption : Option[A] = if (hasNext) Some(head) else None + override def buffered: this.type = this } diff --git a/test/junit/scala/collection/IteratorTest.scala b/test/junit/scala/collection/IteratorTest.scala index 4df29e36c090..09061a3b29c0 100644 --- a/test/junit/scala/collection/IteratorTest.scala +++ b/test/junit/scala/collection/IteratorTest.scala @@ -214,4 +214,32 @@ class IteratorTest { assertSameElements(exp, res) assertEquals(8, counter) // was 14 } + // SI-9691 + @Test def bufferedHeadOptionReturnsValueWithHeadOrNone(): Unit = { + // Checks BufferedIterator returns Some(value) when there is a value + val validHeadOption = List(1,2,3).iterator.buffered.headOption + assertEquals(Some(1), validHeadOption) + // Checks BufferedIterator returns None when there is no value + val invalidHeadOption = List(1,2,3).iterator.drop(10).buffered.headOption + assertEquals(None: Option[Int], invalidHeadOption) + // Checks BufferedIterator returns Some(value) in the last position with a value + val validHeadOptionAtTail = List(1,2,3).iterator.drop(2).buffered.headOption + assertEquals(Some(3), validHeadOptionAtTail) + // Checks BufferedIterator returns None at the first position without a value + val invalidHeadOptionOnePastTail = List(1,2,3).iterator.drop(3).buffered.headOption + assertEquals(None, invalidHeadOptionOnePastTail) + // Checks BufferedIterator returns Some(null) if the next value is null. + val nullHandingList = List(null, "yellow").iterator.buffered.headOption + assertEquals(Some(null), nullHandingList) + // Checks that BufferedIterator is idempotent. That the head is not + // changed by its invocation, nor the headOption by the next call to head. + val it = List(1,2,3).iterator.buffered + val v1 = it.head + val v2 = it.headOption + val v3 = it.head + val v4 = it.headOption + assertEquals(v1, v3) + assertEquals(v2, v4) + assertEquals(Some(v1), v2) + } } From 905b52669973463070112643f9470ddac3c08795 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 5 Jul 2016 11:37:40 -0700 Subject: [PATCH 138/153] SI-9827 MatchIterator advances itself To avoid caveats about calling `next` (or `hasNext`) before using `MatchData` methods on `MatchIterator`, just do it internally as necessary. Note `MatchIterator` behavior in the docs. Added tests showing what people cried about. --- src/library/scala/util/matching/Regex.scala | 142 ++++++++++++------ .../junit/scala/util/matching/RegexTest.scala | 70 ++++++++- 2 files changed, 161 insertions(+), 51 deletions(-) diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index c4a3f1effa4e..ea9f02f85b4b 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -11,21 +11,14 @@ * with the main goal of pulling out information from those matches, or replacing * them with something else. * - * There are four classes and three objects, with most of them being members of - * Regex companion object. [[scala.util.matching.Regex]] is the class users instantiate - * to do regular expression matching. + * [[scala.util.matching.Regex]] is the class users instantiate to do regular expression matching. * - * The remaining classes and objects in the package are used in the following way: - * - * * The companion object to [[scala.util.matching.Regex]] just contains the other members. + * The companion object to [[scala.util.matching.Regex]] contains supporting members: * * [[scala.util.matching.Regex.Match]] makes more information about a match available. - * * [[scala.util.matching.Regex.MatchIterator]] is used to iterate over multiple matches. + * * [[scala.util.matching.Regex.MatchIterator]] is used to iterate over matched strings. * * [[scala.util.matching.Regex.MatchData]] is just a base trait for the above classes. * * [[scala.util.matching.Regex.Groups]] extracts group from a [[scala.util.matching.Regex.Match]] * without recomputing the match. - * * [[scala.util.matching.Regex.Match]] converts a [[scala.util.matching.Regex.Match]] - * into a [[java.lang.String]]. - * */ package scala.util.matching @@ -35,6 +28,7 @@ import java.util.regex.{ Pattern, Matcher } /** A regular expression is used to determine whether a string matches a pattern * and, if it does, to extract or transform the parts that match. * + * === Usage === * This class delegates to the [[java.util.regex]] package of the Java Platform. * See the documentation for [[java.util.regex.Pattern]] for details about * the regular expression syntax for pattern strings. @@ -53,6 +47,7 @@ import java.util.regex.{ Pattern, Matcher } * Since escapes are not processed in multi-line string literals, using triple quotes * avoids having to escape the backslash character, so that `"\\d"` can be written `"""\d"""`. * + * === Extraction === * To extract the capturing groups when a `Regex` is matched, use it as * an extractor in a pattern match: * @@ -92,48 +87,68 @@ import java.util.regex.{ Pattern, Matcher } * } * }}} * + * === Find Matches === * To find or replace matches of the pattern, use the various find and replace methods. - * There is a flavor of each method that produces matched strings and - * another that produces `Match` objects. + * For each method, there is a version for working with matched strings and + * another for working with `Match` objects. * * For example, pattern matching with an unanchored `Regex`, as in the previous example, - * is the same as using `findFirstMatchIn`, except that the findFirst methods return an `Option`, - * or `None` for no match: + * can also be accomplished using `findFirstMatchIn`. The `findFirst` methods return an `Option` + * which is non-empty if a match is found, or `None` for no match: * * {{{ * val dates = "Important dates in history: 2004-01-20, 1958-09-05, 2010-10-06, 2011-07-15" - * val firstDate = date findFirstIn dates getOrElse "No date found." - * val firstYear = for (m <- date findFirstMatchIn dates) yield m group 1 + * val firstDate = date.findFirstIn(dates).getOrElse("No date found.") + * val firstYear = for (m <- date.findFirstMatchIn(dates)) yield m.group(1) * }}} * * To find all matches: * * {{{ - * val allYears = for (m <- date findAllMatchIn dates) yield m group 1 + * val allYears = for (m <- date.findAllMatchIn(dates)) yield m.group(1) * }}} * - * But `findAllIn` returns a special iterator of strings that can be queried for the `MatchData` - * of the last match: + * To iterate over the matched strings, use `findAllIn`, which returns a special iterator + * that can be queried for the `MatchData` of the last match: * * {{{ - * val mi = date findAllIn dates - * val oldies = mi filter (_ => (mi group 1).toInt < 1960) map (s => s"$s: An oldie but goodie.") + * val mi = date.findAllIn(dates) + * while (mi.hasNext) { + * val d = mi.next + * if (mi.group(1).toInt < 1960) println(s"$d: An oldie but goodie.") * }}} * * Note that `findAllIn` finds matches that don't overlap. (See [[findAllIn]] for more examples.) * * {{{ * val num = """(\d+)""".r - * val all = (num findAllIn "123").toList // List("123"), not List("123", "23", "3") + * val all = num.findAllIn("123").toList // List("123"), not List("123", "23", "3") + * }}} + * + * Also, the "current match" of a `MatchIterator` may be advanced by either `hasNext` or `next`. + * By comparison, the `Iterator[Match]` returned by `findAllMatchIn` or `findAllIn.matchData` + * produces `Match` objects that remain valid after the iterator is advanced. + * + * {{{ + * val ns = num.findAllIn("1 2 3") + * ns.start // 0 + * ns.hasNext // true + * ns.start // 2 + * val ms = num.findAllMatchIn("1 2 3") + * val m = ms.next() + * m.start // 0 + * ms.hasNext // true + * m.start // still 0 * }}} * + * === Replace Text === * Text replacement can be performed unconditionally or as a function of the current match: * * {{{ - * val redacted = date replaceAllIn (dates, "XXXX-XX-XX") - * val yearsOnly = date replaceAllIn (dates, m => m group 1) - * val months = (0 to 11) map { i => val c = Calendar.getInstance; c.set(2014, i, 1); f"$c%tb" } - * val reformatted = date replaceAllIn (dates, _ match { case date(y,m,d) => f"${months(m.toInt - 1)} $d, $y" }) + * val redacted = date.replaceAllIn(dates, "XXXX-XX-XX") + * val yearsOnly = date.replaceAllIn(dates, m => m.group(1)) + * val months = (0 to 11).map { i => val c = Calendar.getInstance; c.set(2014, i, 1); f"$c%tb" } + * val reformatted = date.replaceAllIn(dates, _ match { case date(y,m,d) => f"${months(m.toInt - 1)} $d, $y" }) * }}} * * Pattern matching the `Match` against the `Regex` that created it does not reapply the `Regex`. @@ -142,7 +157,7 @@ import java.util.regex.{ Pattern, Matcher } * * {{{ * val docSpree = """2011(?:-\d{2}){2}""".r - * val docView = date replaceAllIn (dates, _ match { + * val docView = date.replaceAllIn(dates, _ match { * case docSpree() => "Historic doc spree!" * case _ => "Something else happened" * }) @@ -338,8 +353,8 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends * {{{ * val hat = "hat[^a]+".r * val hathaway = "hathatthattthatttt" - * val hats = (hat findAllIn hathaway).toList // List(hath, hattth) - * val pos = (hat findAllMatchIn hathaway map (_.start)).toList // List(0, 7) + * val hats = hat.findAllIn(hathaway).toList // List(hath, hattth) + * val pos = hat.findAllMatchIn(hathaway).map(_.start).toList // List(0, 7) * }}} * * To return overlapping matches, it is possible to formulate a regular expression @@ -347,13 +362,13 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends * * {{{ * val madhatter = "(h)(?=(at[^a]+))".r - * val madhats = (madhatter findAllMatchIn hathaway map { + * val madhats = madhatter.findAllMatchIn(hathaway).map { * case madhatter(x,y) => s"$x$y" - * }).toList // List(hath, hatth, hattth, hatttt) + * }.toList // List(hath, hatth, hattth, hatttt) * }}} * - * Attempting to retrieve match information before performing the first match - * or after exhausting the iterator results in [[java.lang.IllegalStateException]]. + * Attempting to retrieve match information after exhausting the iterator + * results in [[java.lang.IllegalStateException]]. * See [[scala.util.matching.Regex.MatchIterator]] for details. * * @param source The text to match against. @@ -743,11 +758,13 @@ object Regex { /** A class to step through a sequence of regex matches. * - * All methods inherited from [[scala.util.matching.Regex.MatchData]] will throw - * a [[java.lang.IllegalStateException]] until the matcher is initialized. The - * matcher can be initialized by calling `hasNext` or `next()` or causing these - * methods to be called, such as by invoking `toString` or iterating through - * the iterator's elements. + * This is an iterator that returns the matched strings. + * + * Queries about match data pertain to the current state of the underlying + * matcher, which is advanced by calling `hasNext` or `next`. + * + * When matches are exhausted, queries about match data will throw + * [[java.lang.IllegalStateException]]. * * @see [[java.util.regex.Matcher]] */ @@ -755,37 +772,62 @@ object Regex { extends AbstractIterator[String] with Iterator[String] with MatchData { self => protected[Regex] val matcher = regex.pattern.matcher(source) - private var nextSeen = false - /** Is there another match? */ + // 0 = not yet matched, 1 = matched, 2 = advanced to match, 3 = no more matches + private[this] var nextSeen = 0 + + /** Return true if `next` will find a match. + * As a side effect, advance the underlying matcher if necessary; + * queries about the current match data pertain to the underlying matcher. + */ def hasNext: Boolean = { - if (!nextSeen) nextSeen = matcher.find() - nextSeen + nextSeen match { + case 0 => nextSeen = if (matcher.find()) 1 else 3 + case 1 => () + case 2 => nextSeen = 0 ; hasNext + case 3 => () + } + nextSeen == 1 // otherwise, 3 } - /** The next matched substring of `source`. */ + /** The next matched substring of `source`. + * As a side effect, advance the underlying matcher if necessary. + */ def next(): String = { - if (!hasNext) throw new NoSuchElementException - nextSeen = false + nextSeen match { + case 0 => if (!hasNext) throw new NoSuchElementException ; next() + case 1 => nextSeen = 2 + case 2 => nextSeen = 0 ; next() + case 3 => throw new NoSuchElementException + } matcher.group } + /** Report emptiness. */ override def toString = super[AbstractIterator].toString + // ensure we're at a match + private[this] def ensure(): Unit = nextSeen match { + case 0 => if (!hasNext) throw new IllegalStateException + case 1 => () + case 2 => () + case 3 => throw new IllegalStateException + } + /** The index of the first matched character. */ - def start: Int = matcher.start + def start: Int = { ensure() ; matcher.start } /** The index of the first matched character in group `i`. */ - def start(i: Int): Int = matcher.start(i) + def start(i: Int): Int = { ensure() ; matcher.start(i) } /** The index of the last matched character. */ - def end: Int = matcher.end + def end: Int = { ensure() ; matcher.end } /** The index following the last matched character in group `i`. */ - def end(i: Int): Int = matcher.end(i) + def end(i: Int): Int = { ensure() ; matcher.end(i) } /** The number of subgroups. */ - def groupCount = matcher.groupCount + def groupCount = { ensure() ; matcher.groupCount } /** Convert to an iterator that yields MatchData elements instead of Strings. */ def matchData: Iterator[Match] = new AbstractIterator[Match] { diff --git a/test/junit/scala/util/matching/RegexTest.scala b/test/junit/scala/util/matching/RegexTest.scala index 06d0445e1ce6..d80e05e512df 100644 --- a/test/junit/scala/util/matching/RegexTest.scala +++ b/test/junit/scala/util/matching/RegexTest.scala @@ -85,8 +85,9 @@ class RegexTest { assertFalse(ms.hasNext) } - //type NoGroup = NoSuchElementException type NoGroup = IllegalArgumentException + type NoMatch = NoSuchElementException + type NoData = IllegalStateException @Test def `SI-9666: throw on bad name`(): Unit = { assertThrows[NoGroup] { @@ -108,4 +109,71 @@ class RegexTest { ms group "Bee" } } + + @Test def `SI-9827 MatchIterator ergonomics`(): Unit = { + val r = "(ab)(cd)".r + val s = "xxxabcdyyyabcdzzz" + assertEquals(3, r.findAllIn(s).start) + assertEquals(5, r.findAllIn(s).start(2)) + locally { + val mi = r.findAllIn(s) + assertTrue(mi.hasNext) + assertEquals(3, mi.start) + assertEquals("abcd", mi.next()) + assertEquals(3, mi.start) + assertTrue(mi.hasNext) + assertEquals(10, mi.start) + } + locally { + val mi = r.findAllIn(s) + assertEquals("abcd", mi.next()) + assertEquals(3, mi.start) + assertEquals("abcd", mi.next()) + assertEquals(10, mi.start) + assertThrows[NoMatch] { mi.next() } + assertThrows[NoData] { mi.start } + } + locally { + val mi = r.findAllIn("") + assertThrows[NoData] { mi.start } + assertThrows[NoMatch] { mi.next() } + } + locally { + val mi = r.findAllMatchIn(s) + val x = mi.next() + assertEquals("abcd", x.matched) + assertEquals(3, x.start) + val y = mi.next() + assertEquals("abcd", y.matched) + assertEquals(10, y.start) + assertThrows[NoMatch] { mi.next() } + assertEquals(3, x.start) + assertEquals(10, y.start) + } + locally { + val regex = "(foo)-(.*)".r + val s = "foo-abc-def" + val result = regex.findAllIn(s) + //result.toString // comment this line to make it not work + val r = (result.group(1), result.group(2)) + assertEquals(("foo", "abc-def"), r) + } + locally { + val t = "this is a test" + val rx = " ".r + val m = rx.findAllIn(t) + assertEquals(5, rx.findAllIn(t).end) + } + locally { + val data = "aaaaabbbbbbccccccc" + val p = "^(.+)(.+)(.+)$".r + val parts = p.findAllIn(data) + val aes = parts.group(1) + val bes = parts.group(2) + val ces = parts.group(3) + assertEquals("ccccccc", ces) + assertEquals("bbbbbb", bes) + assertEquals("aaaaa", aes) + } + } } From f510aa55cfd537788720f9bb89409f0373d8c471 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 6 Jul 2016 21:00:43 +0200 Subject: [PATCH 139/153] Deprecate scala.remote --- src/library/scala/remote.scala | 1 + test/files/jvm/annotations.check | 3 +++ test/files/jvm/annotations.flags | 1 + 3 files changed, 5 insertions(+) create mode 100644 test/files/jvm/annotations.flags diff --git a/src/library/scala/remote.scala b/src/library/scala/remote.scala index 4b16651af95f..7265a1519454 100644 --- a/src/library/scala/remote.scala +++ b/src/library/scala/remote.scala @@ -24,4 +24,5 @@ package scala * } * }}} */ +@deprecated("extend java.rmi.Remote instead and add @throws[java.rmi.RemoteException] to public methods", "2.12.0") class remote extends scala.annotation.StaticAnnotation {} diff --git a/test/files/jvm/annotations.check b/test/files/jvm/annotations.check index a8dc5ecdd16f..43f85ca199cb 100644 --- a/test/files/jvm/annotations.check +++ b/test/files/jvm/annotations.check @@ -1,3 +1,6 @@ +annotations.scala:7: warning: class remote in package scala is deprecated (since 2.12.0): extend java.rmi.Remote instead and add @throws[java.rmi.RemoteException] to public methods + def foo: Unit = () + ^ class java.rmi.RemoteException class java.io.IOException @java.lang.Deprecated() diff --git a/test/files/jvm/annotations.flags b/test/files/jvm/annotations.flags new file mode 100644 index 000000000000..c36e713ab84b --- /dev/null +++ b/test/files/jvm/annotations.flags @@ -0,0 +1 @@ +-deprecation \ No newline at end of file From 4c33a55c9596eea109ac583dc6b5896fec64c0c1 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 6 Jul 2016 21:32:30 +0200 Subject: [PATCH 140/153] Minor cleanups in GenBCode --- .../tools/nsc/backend/jvm/BCodeHelpers.scala | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index df3c2cb3d5ef..d779490ba84e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -883,25 +883,22 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { * * must-single-thread */ - private def addForwarder(isRemoteClass: Boolean, jclass: asm.ClassVisitor, module: Symbol, m: Symbol): Unit = { - def staticForwarderGenericSignature(sym: Symbol, moduleClass: Symbol): String = { - if (sym.isDeferred) null // only add generic signature if method concrete; bug #1745 - else { - // SI-3452 Static forwarder generation uses the same erased signature as the method if forwards to. - // By rights, it should use the signature as-seen-from the module class, and add suitable - // primitive and value-class boxing/unboxing. - // But for now, just like we did in mixin, we just avoid writing a wrong generic signature - // (one that doesn't erase to the actual signature). See run/t3452b for a test case. - val memberTpe = enteringErasure(moduleClass.thisType.memberInfo(sym)) - val erasedMemberType = erasure.erasure(sym)(memberTpe) - if (erasedMemberType =:= sym.info) - getGenericSignature(sym, moduleClass, memberTpe) - else null - } + private def addForwarder(isRemoteClass: Boolean, jclass: asm.ClassVisitor, moduleClass: Symbol, m: Symbol): Unit = { + def staticForwarderGenericSignature: String = { + // SI-3452 Static forwarder generation uses the same erased signature as the method if forwards to. + // By rights, it should use the signature as-seen-from the module class, and add suitable + // primitive and value-class boxing/unboxing. + // But for now, just like we did in mixin, we just avoid writing a wrong generic signature + // (one that doesn't erase to the actual signature). See run/t3452b for a test case. + val memberTpe = enteringErasure(moduleClass.thisType.memberInfo(m)) + val erasedMemberType = erasure.erasure(m)(memberTpe) + if (erasedMemberType =:= m.info) + getGenericSignature(m, moduleClass, memberTpe) + else null } - val moduleName = internalName(module) - val methodInfo = module.thisType.memberInfo(m) + val moduleName = internalName(moduleClass) + val methodInfo = moduleClass.thisType.memberInfo(m) val paramJavaTypes: List[BType] = methodInfo.paramTypes map typeToBType // val paramNames = 0 until paramJavaTypes.length map ("x_" + _) @@ -916,7 +913,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { ) // TODO needed? for(ann <- m.annotations) { ann.symbol.initialize } - val jgensig = staticForwarderGenericSignature(m, module) + val jgensig = staticForwarderGenericSignature addRemoteExceptionAnnot(isRemoteClass, hasPublicBitSet(flags), m) val (throws, others) = m.annotations partition (_.symbol == definitions.ThrowsClass) val thrownExceptions: List[String] = getExceptions(throws) @@ -937,7 +934,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { mirrorMethod.visitCode() - mirrorMethod.visitFieldInsn(asm.Opcodes.GETSTATIC, moduleName, strMODULE_INSTANCE_FIELD, classBTypeFromSymbol(module).descriptor) + mirrorMethod.visitFieldInsn(asm.Opcodes.GETSTATIC, moduleName, strMODULE_INSTANCE_FIELD, classBTypeFromSymbol(moduleClass).descriptor) var index = 0 for(jparamType <- paramJavaTypes) { From e619b033350a3378d650db4c3e5b1bfc83b73d81 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 20 Jul 2016 17:36:54 +0200 Subject: [PATCH 141/153] Upgrade asm to 5.1 The constructor of scala.tools.asm.Handle now takes an additional boolean parameter to denote whether the owner is an interface. --- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 8 +++-- .../nsc/backend/jvm/BTypesFromSymbols.scala | 3 +- .../tools/nsc/backend/jvm/CoreBTypes.scala | 34 +++++++++++++++---- .../tools/nsc/backend/jvm/opt/CallGraph.scala | 16 +-------- .../scala/tools/partest/ASMConverters.scala | 6 ++-- .../scala/reflect/internal/StdNames.scala | 1 + test/files/run/classfile-format-51.scala | 2 +- test/files/run/noInlineUnknownIndy/Test.scala | 7 +++- versions.properties | 2 +- 9 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 55fe47bde61f..acedf8301665 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -1334,11 +1334,13 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { val isStaticMethod = lambdaTarget.hasFlag(Flags.STATIC) def asmType(sym: Symbol) = classBTypeFromSymbol(sym).toASMType + val isInterface = lambdaTarget.owner.isTrait val implMethodHandle = - new asm.Handle(if (lambdaTarget.hasFlag(Flags.STATIC)) asm.Opcodes.H_INVOKESTATIC else if (lambdaTarget.owner.isTrait) asm.Opcodes.H_INVOKEINTERFACE else asm.Opcodes.H_INVOKEVIRTUAL, + new asm.Handle(if (lambdaTarget.hasFlag(Flags.STATIC)) asm.Opcodes.H_INVOKESTATIC else if (isInterface) asm.Opcodes.H_INVOKEINTERFACE else asm.Opcodes.H_INVOKEVIRTUAL, classBTypeFromSymbol(lambdaTarget.owner).internalName, lambdaTarget.name.toString, - methodBTypeFromSymbol(lambdaTarget).descriptor) + methodBTypeFromSymbol(lambdaTarget).descriptor, + /* itf = */ isInterface) val receiver = if (isStaticMethod) Nil else lambdaTarget.owner :: Nil val (capturedParams, lambdaParams) = lambdaTarget.paramss.head.splitAt(lambdaTarget.paramss.head.length - arity) // Requires https://github.com/scala/scala-java8-compat on the runtime classpath @@ -1351,7 +1353,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { val flags = java.lang.invoke.LambdaMetafactory.FLAG_SERIALIZABLE | java.lang.invoke.LambdaMetafactory.FLAG_MARKERS val ScalaSerializable = classBTypeFromSymbol(definitions.SerializableClass).toASMType - bc.jmethod.visitInvokeDynamicInsn(samName, invokedType, lambdaMetaFactoryBootstrapHandle, + bc.jmethod.visitInvokeDynamicInsn(samName, invokedType, lambdaMetaFactoryAltMetafactoryHandle, /* samMethodType = */ samMethodType, /* implMethod = */ implMethodHandle, /* instantiatedMethodType = */ constrainedType, diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 1a4590e7d175..383347a0d321 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -157,7 +157,8 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { def staticHandleFromSymbol(sym: Symbol): asm.Handle = { val owner = if (sym.owner.isModuleClass) sym.owner.linkedClassOfClass else sym.owner val descriptor = methodBTypeFromMethodType(sym.info, isConstructor = false).descriptor - new asm.Handle(asm.Opcodes.H_INVOKESTATIC, classBTypeFromSymbol(owner).internalName, sym.name.encoded, descriptor) + val ownerBType = classBTypeFromSymbol(owner) + new asm.Handle(asm.Opcodes.H_INVOKESTATIC, ownerBType.internalName, sym.name.encoded, descriptor, /* itf = */ ownerBType.isInterface.get) } /** diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index d65380aa1fc7..c2010d282828 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -248,7 +248,22 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { }) } - lazy val lambdaMetaFactoryBootstrapHandle = + lazy val lambdaMetaFactoryMetafactoryHandle = + new asm.Handle(asm.Opcodes.H_INVOKESTATIC, + coreBTypes.jliLambdaMetafactoryRef.internalName, sn.Metafactory.toString, + MethodBType( + List( + coreBTypes.jliMethodHandlesLookupRef, + coreBTypes.StringRef, + coreBTypes.jliMethodTypeRef, + coreBTypes.jliMethodTypeRef, + coreBTypes.jliMethodHandleRef, + coreBTypes.jliMethodTypeRef), + coreBTypes.jliCallSiteRef + ).descriptor, + /* itf = */ coreBTypes.jliLambdaMetafactoryRef.isInterface.get) + + lazy val lambdaMetaFactoryAltMetafactoryHandle = new asm.Handle(asm.Opcodes.H_INVOKESTATIC, coreBTypes.jliLambdaMetafactoryRef.internalName, sn.AltMetafactory.toString, MethodBType( @@ -258,7 +273,8 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { coreBTypes.jliMethodTypeRef, ArrayBType(ObjectRef)), coreBTypes.jliCallSiteRef - ).descriptor) + ).descriptor, + /* itf = */ coreBTypes.jliLambdaMetafactoryRef.isInterface.get) lazy val lambdaDeserializeBootstrapHandle = new scala.tools.asm.Handle(scala.tools.asm.Opcodes.H_INVOKESTATIC, @@ -270,7 +286,8 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { coreBTypes.jliMethodTypeRef ), coreBTypes.jliCallSiteRef - ).descriptor) + ).descriptor, + /* itf = */ coreBTypes.srLambdaDeserialize.isInterface.get) } /** @@ -299,6 +316,7 @@ trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] { def juHashMapRef : ClassBType def juMapRef : ClassBType def jliCallSiteRef : ClassBType + def jliLambdaMetafactoryRef : ClassBType def jliMethodTypeRef : ClassBType def jliSerializedLambdaRef : ClassBType def jliMethodHandleRef : ClassBType @@ -322,8 +340,9 @@ trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] { def srRefConstructors : Map[InternalName, MethodNameAndType] def tupleClassConstructors : Map[InternalName, MethodNameAndType] - def lambdaMetaFactoryBootstrapHandle : asm.Handle - def lambdaDeserializeBootstrapHandle : asm.Handle + def lambdaMetaFactoryMetafactoryHandle : asm.Handle + def lambdaMetaFactoryAltMetafactoryHandle : asm.Handle + def lambdaDeserializeBootstrapHandle : asm.Handle } /** @@ -405,6 +424,7 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def String_valueOf: Symbol = _coreBTypes.String_valueOf - def lambdaMetaFactoryBootstrapHandle = _coreBTypes.lambdaMetaFactoryBootstrapHandle - def lambdaDeserializeBootstrapHandle = _coreBTypes.lambdaDeserializeBootstrapHandle + def lambdaMetaFactoryMetafactoryHandle : asm.Handle = _coreBTypes.lambdaMetaFactoryMetafactoryHandle + def lambdaMetaFactoryAltMetafactoryHandle : asm.Handle = _coreBTypes.lambdaMetaFactoryAltMetafactoryHandle + def lambdaDeserializeBootstrapHandle : asm.Handle = _coreBTypes.lambdaDeserializeBootstrapHandle } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index 5248183337fa..b088b5ee481d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -413,22 +413,8 @@ class CallGraph[BT <: BTypes](val btypes: BT) { final case class LambdaMetaFactoryCall(indy: InvokeDynamicInsnNode, samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type) object LambdaMetaFactoryCall { - private val lambdaMetaFactoryInternalName: InternalName = "java/lang/invoke/LambdaMetafactory" - - private val metafactoryHandle = { - val metafactoryMethodName: String = "metafactory" - val metafactoryDesc: String = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;" - new Handle(Opcodes.H_INVOKESTATIC, lambdaMetaFactoryInternalName, metafactoryMethodName, metafactoryDesc) - } - - private val altMetafactoryHandle = { - val altMetafactoryMethodName: String = "altMetafactory" - val altMetafactoryDesc: String = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;" - new Handle(Opcodes.H_INVOKESTATIC, lambdaMetaFactoryInternalName, altMetafactoryMethodName, altMetafactoryDesc) - } - def unapply(insn: AbstractInsnNode): Option[(InvokeDynamicInsnNode, Type, Handle, Type)] = insn match { - case indy: InvokeDynamicInsnNode if indy.bsm == metafactoryHandle || indy.bsm == altMetafactoryHandle => + case indy: InvokeDynamicInsnNode if indy.bsm == coreBTypes.lambdaMetaFactoryMetafactoryHandle || indy.bsm == coreBTypes.lambdaMetaFactoryAltMetafactoryHandle => indy.bsmArgs match { case Array(samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type, _@_*) => // LambdaMetaFactory performs a number of automatic adaptations when invoking the lambda diff --git a/src/partest-extras/scala/tools/partest/ASMConverters.scala b/src/partest-extras/scala/tools/partest/ASMConverters.scala index a3d849a9c12b..445d3c89c2b3 100644 --- a/src/partest-extras/scala/tools/partest/ASMConverters.scala +++ b/src/partest-extras/scala/tools/partest/ASMConverters.scala @@ -94,7 +94,7 @@ object ASMConverters { case class FrameEntry (`type`: Int, local: List[Any], stack: List[Any]) extends Instruction { def opcode: Int = -1 } case class LineNumber (line: Int, start: Label) extends Instruction { def opcode: Int = -1 } - case class MethodHandle(tag: Int, owner: String, name: String, desc: String) + case class MethodHandle(tag: Int, owner: String, name: String, desc: String, itf: Boolean) case class ExceptionHandler(start: Label, end: Label, handler: Label, desc: Option[String]) case class LocalVariable(name: String, desc: String, signature: Option[String], start: Label, end: Label, index: Int) @@ -147,7 +147,7 @@ object ASMConverters { case _ => a // can be: Class, method Type, primitive constant })(collection.breakOut) - private def convertMethodHandle(h: asm.Handle): MethodHandle = MethodHandle(h.getTag, h.getOwner, h.getName, h.getDesc) + private def convertMethodHandle(h: asm.Handle): MethodHandle = MethodHandle(h.getTag, h.getOwner, h.getName, h.getDesc, h.isInterface) private def convertHandlers(method: t.MethodNode): List[ExceptionHandler] = { method.tryCatchBlocks.asScala.map(h => ExceptionHandler(applyLabel(h.start), applyLabel(h.end), applyLabel(h.handler), Option(h.`type`)))(collection.breakOut) @@ -227,7 +227,7 @@ object ASMConverters { case x => x.asInstanceOf[Object] } - def unconvertMethodHandle(h: MethodHandle): asm.Handle = new asm.Handle(h.tag, h.owner, h.name, h.desc) + def unconvertMethodHandle(h: MethodHandle): asm.Handle = new asm.Handle(h.tag, h.owner, h.name, h.desc, h.itf) def unconvertBsmArgs(a: List[Object]): Array[Object] = a.map({ case h: MethodHandle => unconvertMethodHandle(h) case o => o diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 4f5a545c9559..11b5db979371 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -1171,6 +1171,7 @@ trait StdNames { final val Invoke: TermName = newTermName("invoke") final val InvokeExact: TermName = newTermName("invokeExact") + final val Metafactory: TermName = newTermName("metafactory") final val AltMetafactory: TermName = newTermName("altMetafactory") final val Bootstrap: TermName = newTermName("bootstrap") diff --git a/test/files/run/classfile-format-51.scala b/test/files/run/classfile-format-51.scala index 3a6c4861f193..40eebee19858 100644 --- a/test/files/run/classfile-format-51.scala +++ b/test/files/run/classfile-format-51.scala @@ -80,7 +80,7 @@ object Test extends DirectTest { val test = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "test", s"()Ljava/lang/String;", null, null) test.visitCode() - val bootstrapHandle = new Handle(H_INVOKESTATIC, invokerClassName, bootstrapMethodName, bootStrapMethodType) + val bootstrapHandle = new Handle(H_INVOKESTATIC, invokerClassName, bootstrapMethodName, bootStrapMethodType, /* itf = */ false) test.visitInvokeDynamicInsn("invoke", targetMethodType, bootstrapHandle) test.visitInsn(ARETURN) test.visitMaxs(1, 1) diff --git a/test/files/run/noInlineUnknownIndy/Test.scala b/test/files/run/noInlineUnknownIndy/Test.scala index c6d227b6f2c2..a666146f1588 100644 --- a/test/files/run/noInlineUnknownIndy/Test.scala +++ b/test/files/run/noInlineUnknownIndy/Test.scala @@ -15,7 +15,12 @@ object Test extends DirectTest { } def show(): Unit = { - val unknownBootstrapMethod = new Handle(Opcodes.H_INVOKESTATIC, "not/java/lang/SomeLambdaMetafactory", "notAMetaFactoryMethod", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;") + val unknownBootstrapMethod = new Handle( + Opcodes.H_INVOKESTATIC, + "not/java/lang/SomeLambdaMetafactory", + "notAMetaFactoryMethod", + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;", + /* itf = */ false) modifyClassFile(new File(testOutput.toFile, "A_1.class"))((cn: ClassNode) => { val testMethod = cn.methods.iterator.asScala.find(_.name == "test").head val indy = testMethod.instructions.iterator.asScala.collect({ case i: InvokeDynamicInsnNode => i }).next() diff --git a/versions.properties b/versions.properties index 4d24e0d598af..ed90768780ad 100644 --- a/versions.properties +++ b/versions.properties @@ -27,7 +27,7 @@ scala-parser-combinators.version.number=1.0.4 scala-swing.version.number=2.0.0-M2 scala-swing.version.osgi=2.0.0.M2 jline.version=2.14.1 -scala-asm.version=5.0.4-scala-3 +scala-asm.version=5.1.0-scala-1 # external modules, used internally (not shipped) partest.version.number=1.0.17 From faa4110fc7d8b92cac1e50a6952cdf3bc85d1cdf Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Tue, 19 Jul 2016 15:14:34 +0200 Subject: [PATCH 142/153] Switch Windows CI build to sbt (w/ some sbt build improvements) - Use sbt in `integrate/windows`: This essentially combines the Unix CI jobs `validate/publish-core` and `validate/test`, first publishing a local release built with STARR and then building a new version with that and running all tests on it. - Unify repository handling across build scripts: A new function `generateRepositoriesConfig` in `common`, based on the existing code in `integrate/bootstrap`, writes the `repositories` file for sbt, either with or without an extra bootstrap repository for resolving a previously built version. It is used in all CI scripts to ensure that artifacts are only resolved through the sanctioned proxies and upstream repositories. - The repository URL arguments in `setupPublishCore` and `setupValidateTest` are now optional as well. These commands are used without a URL from `integrate/windows`, which publishes to `local` instead of a temporary remote repository. - `testAll` is now a task instead of a command. It runs the same sequence of sub-tasks as before but does not propagate failures immediately. It always runs all subtasks and reports errors at the end. - The `generateBuildCharacterPropertiesFile` task now includes all properties from `versions.properties` (whose values have potentially been overwritten with `-D` options) in `buildcharacter.properties`. --- build.sbt | 27 ++++++++++++++ project/ScriptCommands.scala | 58 ++++++++++++++---------------- project/VersionUtil.scala | 2 +- scripts/common | 20 +++++++++++ scripts/jobs/integrate/bootstrap | 24 +++---------- scripts/jobs/integrate/windows | 22 +++++++----- scripts/jobs/validate/publish-core | 7 ++-- scripts/jobs/validate/test | 7 ++-- 8 files changed, 102 insertions(+), 65 deletions(-) diff --git a/build.sbt b/build.sbt index 1d4e208da2e3..c789849af6ad 100644 --- a/build.sbt +++ b/build.sbt @@ -769,6 +769,32 @@ lazy val root: Project = (project in file(".")) GenerateAnyVals.run(dir.getAbsoluteFile) state }, + testAll := { + val results = ScriptCommands.sequence[Result[Unit]](List( + (Keys.test in Test in junit).result, + (testOnly in IntegrationTest in testP).toTask(" -- run pos neg jvm").result, + (testOnly in IntegrationTest in testP).toTask(" -- res scalap specialized scalacheck").result, + (testOnly in IntegrationTest in testP).toTask(" -- instrumented presentation").result, + (testOnly in IntegrationTest in testP).toTask(" -- --srcpath scaladoc").result, + (Keys.test in Test in osgiTestFelix).result, + (Keys.test in Test in osgiTestEclipse).result, + (MiMa.mima in library).result, + (MiMa.mima in reflect).result, + Def.task(()).dependsOn( // Run these in parallel: + doc in Compile in library, + doc in Compile in reflect, + doc in Compile in compiler, + doc in Compile in scalap + ).result + )).value + val failed = results.map(_.toEither).collect { case Left(i) => i } + if(failed.nonEmpty) { + val log = streams.value.log + log.error(s"${failed.size} of ${results.length} test tasks failed:") + failed.foreach(i => log.error(s" - $i")) + throw new RuntimeException + } + }, antStyle := false, incOptions := incOptions.value.withNameHashing(!antStyle.value).withAntStyle(antStyle.value) ) @@ -838,6 +864,7 @@ lazy val buildDirectory = settingKey[File]("The directory where all build produc lazy val mkBin = taskKey[Seq[File]]("Generate shell script (bash or Windows batch).") lazy val mkQuick = taskKey[File]("Generate a full build, including scripts, in build/quick") lazy val mkPack = taskKey[File]("Generate a full build, including scripts, in build/pack") +lazy val testAll = taskKey[Unit]("Run all test tasks sequentially") // Defining these settings is somewhat redundant as we also redefine settings that depend on them. // However, IntelliJ's project import works better when these are set correctly. diff --git a/project/ScriptCommands.scala b/project/ScriptCommands.scala index accbadbbf66c..8d5d09943a56 100644 --- a/project/ScriptCommands.scala +++ b/project/ScriptCommands.scala @@ -7,24 +7,29 @@ object ScriptCommands { def all = Seq( setupPublishCore, setupValidateTest, - setupBootstrapStarr, setupBootstrapLocker, setupBootstrapQuick, setupBootstrapPublish, - testAll + setupBootstrapStarr, setupBootstrapLocker, setupBootstrapQuick, setupBootstrapPublish ) - /** Set up the environment for `validate/publish-core`. The argument is the Artifactory snapshot repository URL. */ - def setupPublishCore = setup("setupPublishCore") { case Seq(url) => + /** Set up the environment for `validate/publish-core`. + * The optional argument is the Artifactory snapshot repository URL. */ + def setupPublishCore = setup("setupPublishCore") { args => Seq( baseVersionSuffix in Global := "SHA-SNAPSHOT" - ) ++ publishTarget(url) ++ noDocs ++ enableOptimizer + ) ++ (args match { + case Seq(url) => publishTarget(url) + case Nil => Nil + }) ++ noDocs ++ enableOptimizer } - /** Set up the environment for `validate/test`. The argument is the Artifactory snapshot repository URL. */ - def setupValidateTest = setup("setupValidateTest") { case Seq(url) => - //TODO When ant is gone, pass starr version as an argument to this command instead of using version.properties + /** Set up the environment for `validate/test`. + * The optional argument is the Artifactory snapshot repository URL. */ + def setupValidateTest = setup("setupValidateTest") { args => Seq( - resolvers in Global += "scala-pr" at url, testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff")) - ) ++ enableOptimizer + ) ++ (args match { + case Seq(url) => Seq(resolvers in Global += "scala-pr" at url) + case Nil => Nil + }) ++ enableOptimizer } /** Set up the environment for building STARR in `validate/bootstrap`. The arguments are: @@ -63,9 +68,7 @@ object ScriptCommands { /** Set up the environment for publishing in `validate/bootstrap`. The arguments are: * - Temporary bootstrap repository URL for resolving modules * - Version number to publish - * All artifacts are published to Sonatype. GPG signing has to be configured from the - * shell script after `setupBootstrapPublish` because we don't pull the GPG plugin in - * by default, so we cannot reference its keys statically. */ + * All artifacts are published to Sonatype. */ def setupBootstrapPublish = setup("setupBootstrapPublish") { case Seq(url, ver) => // Define a copy of the setting key here in case the plugin is not part of the build val pgpPassphrase = SettingKey[Option[Array[Char]]]("pgp-passphrase", "The passphrase associated with the secret used to sign artifacts.", KeyRanks.BSetting) @@ -95,25 +98,18 @@ object ScriptCommands { publishArtifact in (Compile, packageDoc) in ThisBuild := false ) - private[this] def publishTarget(url: String) = Seq( + private[this] def publishTarget(url: String) = { // Append build.timestamp to Artifactory URL to get consistent build numbers (see https://github.com/sbt/sbt/issues/2088): - publishTo in Global := Some("scala-pr-publish" at url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis) - ) + val url2 = if(url.startsWith("file:")) url else url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis + Seq(publishTo in Global := Some("scala-pr-publish" at url2)) + } - def testAll = Command.command("testAll") { state => - val cmds = Seq( - "test", - "partest run pos neg jvm", - "partest res scalap specialized scalacheck", - "partest instrumented presentation", - "partest --srcpath scaladoc", - "osgiTestFelix/test", - "osgiTestEclipse/test", - "library/mima", - "reflect/mima", - "doc" - ) - state.log.info(cmds.mkString("Running all tests: \"", "\", \"", "\"")) - cmds ::: state + /** Like `Def.sequential` but accumulate all results */ + def sequence[B](tasks: List[Def.Initialize[Task[B]]]): Def.Initialize[Task[List[B]]] = tasks match { + case Nil => Def.task { Nil } + case x :: xs => Def.taskDyn { + val v = x.value + sequence(xs).apply((t: Task[List[B]]) => t.map(l => v :: l)) + } } } diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala index 148fdfbc2343..6fe2b004f783 100644 --- a/project/VersionUtil.scala +++ b/project/VersionUtil.scala @@ -94,7 +94,7 @@ object VersionUtil { } private lazy val generateBuildCharacterPropertiesFileImpl: Def.Initialize[Task[File]] = Def.task { - writeProps(versionProperties.value.toMap, (baseDirectory in ThisBuild).value / "buildcharacter.properties") + writeProps(versionProperties.value.toMap ++ versionProps, (baseDirectory in ThisBuild).value / "buildcharacter.properties") } private def writeProps(m: Map[String, String], propFile: File): File = { diff --git a/scripts/common b/scripts/common index bfddf3d149f3..95389e5495c1 100644 --- a/scripts/common +++ b/scripts/common @@ -154,3 +154,23 @@ EOF fi popd } + +# Generate a repositories file with all allowed repositories in our build environment. +# Takes one optional argument, the private repository URL. +# See http://www.scala-sbt.org/0.13/docs/Proxy-Repositories.html +function generateRepositoriesConfig() { + jcenterCacheUrl=${jcenterCacheUrl-"https://scala-ci.typesafe.com/artifactory/jcenter/"} + sbtRepositoryConfig="$scriptsDir/sbt-repositories-config" + echo > "$sbtRepositoryConfig" '[repositories]' + if [ -n "$1" ] + then + echo >> "$sbtRepositoryConfig" " private-repo: $1" + fi + cat >> "$sbtRepositoryConfig" << EOF + jcenter-cache: $jcenterCacheUrl + typesafe-ivy-releases: https://dl.bintray.com/typesafe/ivy-releases/, [organisation]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly + sbt-plugin-releases: https://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] + maven-central + local +EOF +} diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index bdc50323a8c6..4d5dae89a201 100644 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -85,10 +85,8 @@ moduleVersioning=${moduleVersioning-"versions.properties"} publishPrivateTask=${publishPrivateTask-"publish"} -publishSonatypeTaskCore=${publishSonatypeTaskCore-"publish-signed"} -publishSonatypeTaskModules=${publishSonatypeTaskModules-"publish-signed"} -publishStarrPrivateTask=${publishStarrPrivateTask-$publishPrivateTask} # set to "init" to speed up testing of the script (if you already built STARR before) -publishLockerPrivateTask=${publishLockerPrivateTask-$publishPrivateTask} # set to "init" to speed up testing of the script (if you already built locker before) +publishSonatypeTaskCore=${publishSonatypeTaskCore-"publishSigned"} +publishSonatypeTaskModules=${publishSonatypeTaskModules-"publishSigned"} forceRebuild=${forceRebuild-no} @@ -111,21 +109,7 @@ mkdir -p $baseDir/resolutionScratch_ # repo used to publish "locker" scala to (to start the bootstrap) releaseTempRepoCred="private-repo" releaseTempRepoUrl=${releaseTempRepoUrl-"https://scala-ci.typesafe.com/artifactory/scala-release-temp/"} -jcenterCacheUrl=${jcenterCacheUrl-"https://scala-ci.typesafe.com/artifactory/jcenter/"} - -# Used below in sbtArgs since we use a dedicated repository to share artifcacts between jobs, -# so we need to configure SBT to use these rather than its default, Maven Central. -# See http://www.scala-sbt.org/0.13/docs/Proxy-Repositories.html -sbtRepositoryConfig="$scriptsDir/repositories-scala-release" -cat > "$sbtRepositoryConfig" << EOF -[repositories] - private-repo: $releaseTempRepoUrl - jcenter-cache: $jcenterCacheUrl - typesafe-ivy-releases: https://dl.bintray.com/typesafe/ivy-releases/, [organisation]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly - sbt-plugin-releases: https://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] - maven-central - local -EOF +generateRepositoriesConfig $releaseTempRepoUrl ##### git gfxd() { @@ -575,7 +559,7 @@ publishSonatype() { -Dstarr.version=$SCALA_VER \ ${updatedModuleVersions[@]} \ "setupBootstrapPublish $releaseTempRepoUrl $SCALA_VER" \ - publishSigned | grep -v "was too long to be displayed in the webview, and will be left out" + $publishSonatypeTaskCore | grep -v "was too long to be displayed in the webview, and will be left out" echo "### Publishing modules to sonatype" # build/test/publish scala core modules to sonatype (this will start a new staging repo) diff --git a/scripts/jobs/integrate/windows b/scripts/jobs/integrate/windows index ba48c5bc2541..5e04b0b38065 100755 --- a/scripts/jobs/integrate/windows +++ b/scripts/jobs/integrate/windows @@ -1,15 +1,19 @@ #!/bin/bash -./pull-binary-libs.sh - -export ANT_OPTS="-Dfile.encoding=UTF-8 -server -XX:+AggressiveOpts -XX:+UseParNewGC -Xmx2G -Xss1M -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=128M" - -# TODO: don't hardcode these paths -- should be in scala/scala-jenkins-infra, passed in through env vars from jenkins -export PATH='/cygdrive/c/Program Files/Java/jdk1.8.0_92/bin:/cygdrive/c/apache-ant-1.9.6/bin:/cygdrive/c/Program Files (x86)/Git-2.5.3/Cmd:/bin:/usr/bin:' -export JAVA_HOME='C:/Program Files/Java/jdk1.8.0_92' +baseDir=${WORKSPACE-`pwd`} +scriptsDir="$baseDir/scripts" +. $scriptsDir/common java -version javac -version -ant -version -ant test-opt +generateRepositoriesConfig + +SBT="java $JAVA_OPTS -Dsbt.ivy.home=$WORKSPACE/.ivy2 -jar $sbtLauncher -Dsbt.override.build.repos=true -Dsbt.repository.config=$sbtRepositoryConfig" + +# Build locker with STARR +$SBT --warn "setupPublishCore" generateBuildCharacterPropertiesFile publishLocal + +# Build quick and run the tests +parseScalaProperties buildcharacter.properties +$SBT -Dstarr.version=$maven_version_number --warn "setupValidateTest" testAll | grep -v "was too long to be displayed in the webview, and will be left out" diff --git a/scripts/jobs/validate/publish-core b/scripts/jobs/validate/publish-core index b0bfd480836a..c71fbd12b796 100755 --- a/scripts/jobs/validate/publish-core +++ b/scripts/jobs/validate/publish-core @@ -9,6 +9,9 @@ baseDir=${WORKSPACE-`pwd`} scriptsDir="$baseDir/scripts" . $scriptsDir/common +generateRepositoriesConfig $prRepoUrl +SBT="$SBT_CMD -Dsbt.override.build.repos=true -Dsbt.repository.config=$sbtRepositoryConfig" + case $prDryRun in yep) echo "DRY RUN" @@ -16,7 +19,7 @@ case $prDryRun in ;; *) echo ">>> Getting Scala version number." - $SBT_CMD --warn "setupPublishCore $prRepoUrl" generateBuildCharacterPropertiesFile + $SBT --warn "setupPublishCore $prRepoUrl" generateBuildCharacterPropertiesFile parseScalaProperties buildcharacter.properties # produce maven_version_number echo ">>> Checking availability of Scala ${maven_version_number} in $prRepoUrl." @@ -27,7 +30,7 @@ case $prDryRun in if $libraryAvailable && $reflectAvailable && $compilerAvailable; then echo "Scala core already built!" else - $SBT_CMD --warn "setupPublishCore $prRepoUrl" publish + $SBT --warn "setupPublishCore $prRepoUrl" publish fi mv buildcharacter.properties jenkins.properties # parsed by the jenkins job diff --git a/scripts/jobs/validate/test b/scripts/jobs/validate/test index dd36c5db18ce..9938319dd843 100755 --- a/scripts/jobs/validate/test +++ b/scripts/jobs/validate/test @@ -4,6 +4,9 @@ baseDir=${WORKSPACE-`pwd`} scriptsDir="$baseDir/scripts" . $scriptsDir/common +generateRepositoriesConfig $prRepoUrl +SBT="$SBT_CMD -Dsbt.override.build.repos=true -Dsbt.repository.config=$sbtRepositoryConfig" + case $prDryRun in yep) @@ -15,12 +18,12 @@ case $prDryRun in # build quick using STARR built upstream, as specified by scalaVersion # (in that sense it's locker, since it was built with starr by that upstream job); # and run JUnit tests, partest, OSGi tests, MiMa and scaladoc - $SBT_CMD \ + $SBT \ -Dstarr.version=$scalaVersion \ --warn \ "setupValidateTest $prRepoUrl" \ $testExtraArgs \ - testAll + testAll | grep -v "was too long to be displayed in the webview, and will be left out" ;; From 9a2486087a9739108265e7830ebaa96373605d02 Mon Sep 17 00:00:00 2001 From: Carsten Varming Date: Wed, 20 Jul 2016 23:57:35 -0400 Subject: [PATCH 143/153] SI-8774 Null link fields in mutable hash maps on removal. --- src/library/scala/collection/mutable/HashTable.scala | 5 ++++- src/library/scala/collection/mutable/LinkedHashMap.scala | 2 ++ src/library/scala/collection/mutable/LinkedHashSet.scala | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala index b48a32fa3749..bb15788bdf45 100644 --- a/src/library/scala/collection/mutable/HashTable.scala +++ b/src/library/scala/collection/mutable/HashTable.scala @@ -183,6 +183,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU table(h) = e.next tableSize = tableSize - 1 nnSizeMapRemove(h) + e.next = null return e } else { var e1 = e.next @@ -194,6 +195,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU e.next = e1.next tableSize = tableSize - 1 nnSizeMapRemove(h) + e1.next = null return e1 } } @@ -227,8 +229,9 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU var es = iterTable(idx) while (es != null) { + val next = es.next // Cache next in case f removes es. f(es.asInstanceOf[Entry]) - es = es.next + es = next while (es == null && idx > 0) { idx -= 1 diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala index 275f49067537..a731b1bbdc07 100644 --- a/src/library/scala/collection/mutable/LinkedHashMap.scala +++ b/src/library/scala/collection/mutable/LinkedHashMap.scala @@ -81,6 +81,8 @@ class LinkedHashMap[A, B] extends AbstractMap[A, B] else e.earlier.later = e.later if (e.later eq null) lastEntry = e.earlier else e.later.earlier = e.earlier + e.earlier = null // Null references to prevent nepotism + e.later = null Some(e.value) } } diff --git a/src/library/scala/collection/mutable/LinkedHashSet.scala b/src/library/scala/collection/mutable/LinkedHashSet.scala index 756a2f73c16c..f00cbd90dc7a 100644 --- a/src/library/scala/collection/mutable/LinkedHashSet.scala +++ b/src/library/scala/collection/mutable/LinkedHashSet.scala @@ -73,6 +73,8 @@ class LinkedHashSet[A] extends AbstractSet[A] else e.earlier.later = e.later if (e.later eq null) lastEntry = e.earlier else e.later.earlier = e.earlier + e.earlier = null // Null references to prevent nepotism + e.later = null true } } From 04649c74c47af1b6e21648e4dfe7db0417f3a9ba Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 22 Jul 2016 09:50:04 +1000 Subject: [PATCH 144/153] SD-186 Fix positions in trait method bytecode Concrete, non private methods in traits are translated into a static method with an explicit `$this` parameter. After this translation, the references to `$this` (subistuted for `this` in user written code) where being positioned at the position of the method, which makes debugging unpleasant. This commit leaves the `Ident($this)` trees unpositioned. This is analagous to what we do in the body of extension methods, which is the other user of `ThisSubstitutor`. It would be more correct to copy the position of each `This` tree over to the substituted tree. That would let us set a breakpoint on a line that _only_ contained `this`. But in 99% of cases users won't be able to spot the difference, so I've opted for the tried and tested approach here. --- .../scala/tools/nsc/ast/TreeGen.scala | 2 +- .../tools/nsc/backend/jvm/BytecodeTest.scala | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index bc89609a596c..2a4b1b6738cc 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -350,7 +350,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { case mt @ MethodType(params, res) => copyMethodType(mt, selfParamSym :: params, res) }) val selfParam = ValDef(selfParamSym) - val rhs = orig.rhs.substituteThis(newSym.owner, atPos(newSym.pos)(gen.mkAttributedIdent(selfParamSym))) + val rhs = orig.rhs.substituteThis(newSym.owner, gen.mkAttributedIdent(selfParamSym)) // SD-186 intentionally leaving Ident($this) is unpositioned .substituteSymbols(origParams, newSym.info.params.drop(1)).changeOwner(origSym -> newSym) treeCopy.DefDef(orig, orig.mods, orig.name, orig.tparams, (selfParam :: orig.vparamss.head) :: Nil, orig.tpt, rhs).setSymbol(newSym) } diff --git a/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala index b2ee8b3a4570..5904cb2441dc 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala @@ -168,4 +168,23 @@ class BytecodeTest extends BytecodeTesting { assertEquals(x.start, labels(1)) assertEquals(x.end, labels(7)) } + + @Test // wrong line numbers for rewritten `this` references in trait static methods + def sd186_traitLineNumber(): Unit = { + val code = + """trait T { + | def t(): Unit = { + | toString + | toString + | } + |} + """.stripMargin + val t = compileClass(code) + val tMethod = getMethod(t, "t$") + val invoke = Invoke(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false) + assertSameCode(tMethod.instructions, + List(Label(0), LineNumber(3, Label(0)), VarOp(ALOAD, 0), invoke, Op(POP), + Label(5), LineNumber(4, Label(5)), VarOp(ALOAD, 0), invoke, Op(POP), Op(RETURN), Label(11)) + ) + } } From caeedcf7f158cb7043e988d0a0ce7a216d973237 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Thu, 7 Jul 2016 10:19:55 -1000 Subject: [PATCH 145/153] Disable stub warning by default. When we create a class symbols from a classpath elements, references to other classes that are absent from the classpath are represented as references to "stub symbols". This is not a fatal error; for instance if these references are from the signature of a method that isn't called from the program being compiled, we don't need to know anything about them. A subsequent attempt to look at the type of a stub symbols will trigger a compile error. Currently, the creation of a stub symbol incurs a warning. This commit removes that warning on the basis that it isn't something users need to worry about. javac doesn't emit a comparable warning. The warning is still issued under any of `-verbose` / `-Xdev` / `-Ydebug`. --- .../scala/tools/nsc/symtab/classfile/ClassfileParser.scala | 2 +- test/files/run/t7439.check | 2 +- test/files/run/t8442.check | 2 +- test/files/run/t9268.check | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 0533d420cdb4..f8c1a0d08278 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -366,7 +366,7 @@ abstract class ClassfileParser { // - better owner than `NoSymbol` // - remove eager warning val msg = s"Class $name not found - continuing with a stub." - if (!settings.isScaladoc) warning(msg) + if ((!settings.isScaladoc) && (settings.verbose || settings.developer)) warning(msg) return NoSymbol.newStubSymbol(name.toTypeName, msg) } val completer = new loaders.ClassfileLoader(file) diff --git a/test/files/run/t7439.check b/test/files/run/t7439.check index 9ea09f9c4094..b95884311a71 100644 --- a/test/files/run/t7439.check +++ b/test/files/run/t7439.check @@ -1,2 +1,2 @@ Recompiling after deleting t7439-run.obj/A_1.class -pos: NoPosition Class A_1 not found - continuing with a stub. WARNING + diff --git a/test/files/run/t8442.check b/test/files/run/t8442.check index ce9e8b52ff21..8b137891791f 100644 --- a/test/files/run/t8442.check +++ b/test/files/run/t8442.check @@ -1 +1 @@ -pos: NoPosition Class A_1 not found - continuing with a stub. WARNING + diff --git a/test/files/run/t9268.check b/test/files/run/t9268.check index 90ef940eb336..60afcbb6484e 100644 --- a/test/files/run/t9268.check +++ b/test/files/run/t9268.check @@ -1,5 +1,4 @@ Compiling Client1 -pos: NoPosition Class Waiter not found - continuing with a stub. WARNING + Compiling Client2 -pos: NoPosition Class Waiter not found - continuing with a stub. WARNING pos: NoPosition Unable to locate class corresponding to inner class entry for Predicate in owner Waiter ERROR From 3e64fdda48b8f2506756fc458f01f2e549d71720 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 14 Jul 2016 11:02:36 +1000 Subject: [PATCH 146/153] SD-120 Non FunctionN lambdas should not be universally serializable Instead, we follow the example set by javac, and predicate serializability of bot anon-class and invokedynamic-based lambdas on whether or not the SAM type extends java.io.Serializable. Fixes https://github.com/scala/scala-dev/issues/120 --- .../scala/tools/nsc/ast/TreeGen.scala | 18 +++---- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 38 +++++++-------- .../tools/nsc/transform/Delambdafy.scala | 6 ++- test/files/run/lambda-serialization.scala | 2 +- test/files/run/sammy_seriazable.scala | 47 +++++++++++++++++++ 5 files changed, 80 insertions(+), 31 deletions(-) create mode 100644 test/files/run/sammy_seriazable.scala diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index bc89609a596c..f53fb336e932 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -355,20 +355,22 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { treeCopy.DefDef(orig, orig.mods, orig.name, orig.tparams, (selfParam :: orig.vparamss.head) :: Nil, orig.tpt, rhs).setSymbol(newSym) } - // TODO: the rewrite to AbstractFunction is superfluous once we compile FunctionN to a SAM type (aka functional interface) - def functionClassType(fun: Function): Type = - if (isFunctionType(fun.tpe)) abstractFunctionType(fun.vparams.map(_.symbol.tpe), fun.body.tpe.deconst) - else fun.tpe - def expandFunction(localTyper: analyzer.Typer)(fun: Function, inConstructorFlag: Long): Tree = { - val parents = addSerializable(functionClassType(fun)) - val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation + val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) + val parents = if (isFunctionType(fun.tpe)) { + anonClass addAnnotation SerialVersionUIDAnnotation + addSerializable(abstractFunctionType(fun.vparams.map(_.symbol.tpe), fun.body.tpe.deconst)) + } else { + if (fun.tpe.typeSymbol.isSubClass(JavaSerializableClass)) + anonClass addAnnotation SerialVersionUIDAnnotation + fun.tpe :: Nil + } + anonClass setInfo ClassInfoType(parents, newScope, anonClass) // The original owner is used in the backend for the EnclosingMethod attribute. If fun is // nested in a value-class method, its owner was already changed to the extension method. // Saving the original owner allows getting the source structure from the class symbol. defineOriginalOwner(anonClass, fun.symbol.originalOwner) - anonClass setInfo ClassInfoType(parents, newScope, anonClass) val samDef = mkMethodFromFunction(localTyper)(anonClass, fun) anonClass.info.decls enter samDef.symbol diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index acedf8301665..d5c4b5e20161 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -15,7 +15,7 @@ import scala.tools.asm import GenBCode._ import BackendReporting._ import scala.tools.asm.Opcodes -import scala.tools.asm.tree.MethodInsnNode +import scala.tools.asm.tree.{MethodInsnNode, MethodNode} import scala.tools.nsc.backend.jvm.BCodeHelpers.{InvokeStyle, TestOp} /* @@ -630,7 +630,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { case Apply(fun, args) if app.hasAttachment[delambdafy.LambdaMetaFactoryCapable] => val attachment = app.attachments.get[delambdafy.LambdaMetaFactoryCapable].get genLoadArguments(args, paramTKs(app)) - genInvokeDynamicLambda(attachment.target, attachment.arity, attachment.functionalInterface, attachment.sam) + genInvokeDynamicLambda(attachment.target, attachment.arity, attachment.functionalInterface, attachment.sam, attachment.isSerializable, attachment.addScalaSerializableMarker) generatedType = methodBTypeFromSymbol(fun.symbol).returnType case Apply(fun, List(expr)) if currentRun.runDefinitions.isBox(fun.symbol) => @@ -1330,7 +1330,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { def genSynchronized(tree: Apply, expectedType: BType): BType def genLoadTry(tree: Try): BType - def genInvokeDynamicLambda(lambdaTarget: Symbol, arity: Int, functionalInterface: Symbol, sam: Symbol) { + def genInvokeDynamicLambda(lambdaTarget: Symbol, arity: Int, functionalInterface: Symbol, sam: Symbol, isSerializable: Boolean, addScalaSerializableMarker: Boolean) { val isStaticMethod = lambdaTarget.hasFlag(Flags.STATIC) def asmType(sym: Symbol) = classBTypeFromSymbol(sym).toASMType @@ -1343,26 +1343,24 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { /* itf = */ isInterface) val receiver = if (isStaticMethod) Nil else lambdaTarget.owner :: Nil val (capturedParams, lambdaParams) = lambdaTarget.paramss.head.splitAt(lambdaTarget.paramss.head.length - arity) - // Requires https://github.com/scala/scala-java8-compat on the runtime classpath val invokedType = asm.Type.getMethodDescriptor(asmType(functionalInterface), (receiver ::: capturedParams).map(sym => typeToBType(sym.info).toASMType): _*) - val constrainedType = new MethodBType(lambdaParams.map(p => typeToBType(p.tpe)), typeToBType(lambdaTarget.tpe.resultType)).toASMType - val samName = sam.name.toString val samMethodType = methodBTypeFromSymbol(sam).toASMType - - val flags = java.lang.invoke.LambdaMetafactory.FLAG_SERIALIZABLE | java.lang.invoke.LambdaMetafactory.FLAG_MARKERS - - val ScalaSerializable = classBTypeFromSymbol(definitions.SerializableClass).toASMType - bc.jmethod.visitInvokeDynamicInsn(samName, invokedType, lambdaMetaFactoryAltMetafactoryHandle, - /* samMethodType = */ samMethodType, - /* implMethod = */ implMethodHandle, - /* instantiatedMethodType = */ constrainedType, - /* flags = */ flags.asInstanceOf[AnyRef], - /* markerInterfaceCount = */ 1.asInstanceOf[AnyRef], - /* markerInterfaces[0] = */ ScalaSerializable, - /* bridgeCount = */ 0.asInstanceOf[AnyRef] - ) - indyLambdaHosts += cnode.name + val markers = if (addScalaSerializableMarker) classBTypeFromSymbol(definitions.SerializableClass).toASMType :: Nil else Nil + visitInvokeDynamicInsnLMF(bc.jmethod, sam.name.toString, invokedType, samMethodType, implMethodHandle, constrainedType, isSerializable, markers) + if (isSerializable) + indyLambdaHosts += cnode.name } } + + private def visitInvokeDynamicInsnLMF(jmethod: MethodNode, samName: String, invokedType: String, samMethodType: asm.Type, + implMethodHandle: asm.Handle, instantiatedMethodType: asm.Type, + serializable: Boolean, markerInterfaces: Seq[asm.Type]) = { + import java.lang.invoke.LambdaMetafactory.{FLAG_MARKERS, FLAG_SERIALIZABLE} + def flagIf(b: Boolean, flag: Int): Int = if (b) flag else 0 + val flags = FLAG_MARKERS | flagIf(serializable, FLAG_SERIALIZABLE) + val bsmArgs = Seq(samMethodType, implMethodHandle, instantiatedMethodType, Int.box(flags), Int.box(markerInterfaces.length)) ++ markerInterfaces + jmethod.visitInvokeDynamicInsn(samName, invokedType, lambdaMetaFactoryAltMetafactoryHandle, bsmArgs: _*) + } + } diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 804bcddb7b88..5e5b9fd25058 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -28,7 +28,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre /** the following two members override abstract members in Transform */ val phaseName: String = "delambdafy" - final case class LambdaMetaFactoryCapable(target: Symbol, arity: Int, functionalInterface: Symbol, sam: Symbol) + final case class LambdaMetaFactoryCapable(target: Symbol, arity: Int, functionalInterface: Symbol, sam: Symbol, isSerializable: Boolean, addScalaSerializableMarker: Boolean) /** * Get the symbol of the target lifted lambda body method from a function. I.e. if @@ -95,6 +95,8 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // no need for adaptation when the implemented sam is of a specialized built-in function type val lambdaTarget = if (isSpecialized) target else createBoxingBridgeMethodIfNeeded(fun, target, functionalInterface, sam) + val isSerializable = samUserDefined == NoSymbol || samUserDefined.owner.isNonBottomSubClass(definitions.JavaSerializableClass) + val addScalaSerializableMarker = samUserDefined == NoSymbol // The backend needs to know the target of the lambda and the functional interface in order // to emit the invokedynamic instruction. We pass this information as tree attachment. @@ -102,7 +104,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // see https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html // instantiatedMethodType is derived from lambdaTarget's signature // samMethodType is derived from samOf(functionalInterface)'s signature - apply.updateAttachment(LambdaMetaFactoryCapable(lambdaTarget, fun.vparams.length, functionalInterface, sam)) + apply.updateAttachment(LambdaMetaFactoryCapable(lambdaTarget, fun.vparams.length, functionalInterface, sam, isSerializable, addScalaSerializableMarker)) apply } diff --git a/test/files/run/lambda-serialization.scala b/test/files/run/lambda-serialization.scala index 0eee1193d79d..08e235b1cb9b 100644 --- a/test/files/run/lambda-serialization.scala +++ b/test/files/run/lambda-serialization.scala @@ -1,6 +1,6 @@ import java.io.{ByteArrayInputStream, ObjectInputStream, ObjectOutputStream, ByteArrayOutputStream} -trait IntToString { def apply(i: Int): String } +trait IntToString extends java.io.Serializable { def apply(i: Int): String } object Test { def main(args: Array[String]): Unit = { diff --git a/test/files/run/sammy_seriazable.scala b/test/files/run/sammy_seriazable.scala new file mode 100644 index 000000000000..458b99238a23 --- /dev/null +++ b/test/files/run/sammy_seriazable.scala @@ -0,0 +1,47 @@ +import java.io._ + +trait NotSerializableInterface { def apply(a: Any): Any } +abstract class NotSerializableClass { def apply(a: Any): Any } +// SAM type that supports lambdas-as-invoke-dynamic +trait IsSerializableInterface extends java.io.Serializable { def apply(a: Any): Any } +// SAM type that still requires lambdas-as-anonhmous-classes +abstract class IsSerializableClass extends java.io.Serializable { def apply(a: Any): Any } + +object Test { + def main(args: Array[String]) { + val nsi: NotSerializableInterface = x => x + val nsc: NotSerializableClass = x => x + + import SerDes._ + assertNotSerializable(nsi) + assertNotSerializable(nsc) + assert(serializeDeserialize[IsSerializableInterface](x => x).apply("foo") == "foo") + assert(serializeDeserialize[IsSerializableClass](x => x).apply("foo") == "foo") + assert(ObjectStreamClass.lookup(((x => x): IsSerializableClass).getClass).getSerialVersionUID == 0) + } +} + +object SerDes { + def assertNotSerializable(a: AnyRef): Unit = { + try { + serialize(a) + assert(false) + } catch { + case _: NotSerializableException => // okay + } + } + + def serialize(obj: AnyRef): Array[Byte] = { + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + buffer.toByteArray + } + + def deserialize(a: Array[Byte]): AnyRef = { + val in = new ObjectInputStream(new ByteArrayInputStream(a)) + in.readObject + } + + def serializeDeserialize[T <: AnyRef](obj: T) = deserialize(serialize(obj)).asInstanceOf[T] +} From dc326cd8213ef15cb7647dddfc5144ae47b01b5e Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Thu, 19 Nov 2015 19:32:19 +0100 Subject: [PATCH 147/153] SI-9560 Remove dependency on parser-combinators/json Also update a few example IDE files for Eclipse and IntelliJ. This drops the dependency by integrating the bare minimum functionality to keep things working. --- build.sbt | 7 +- build.xml | 13 ++-- dbuild-meta.json | 5 -- src/build/bnd/scala-compiler.bnd | 1 - src/build/dbuild-meta-json-gen.scala | 5 +- src/build/maven/scala-compiler-doc-pom.xml | 5 -- src/build/maven/scala-compiler-pom.xml | 5 -- src/eclipse/interactive/.classpath | 2 +- src/eclipse/partest/.classpath | 4 +- src/eclipse/repl/.classpath | 2 +- src/eclipse/scala-compiler/.classpath | 2 +- src/eclipse/scaladoc/.classpath | 7 +- src/eclipse/test-junit/.classpath | 4 +- src/intellij/scala.ipr.SAMPLE | 70 ++++++++----------- .../tools/nsc/doc/html/page/IndexScript.scala | 21 +++--- .../scala/tools/nsc/doc/html/page/JSON.scala | 56 +++++++++++++++ 16 files changed, 116 insertions(+), 93 deletions(-) create mode 100644 src/scaladoc/scala/tools/nsc/doc/html/page/JSON.scala diff --git a/build.sbt b/build.sbt index 1d4e208da2e3..78f30c220fd1 100644 --- a/build.sbt +++ b/build.sbt @@ -56,9 +56,9 @@ import VersionUtil._ // Scala dependencies: -val scalaParserCombinatorsDep = scalaDep("org.scala-lang.modules", "scala-parser-combinators") val scalaSwingDep = scalaDep("org.scala-lang.modules", "scala-swing") val scalaXmlDep = scalaDep("org.scala-lang.modules", "scala-xml") +val scalaParserCombinatorsDep = scalaDep("org.scala-lang.modules", "scala-parser-combinators") val partestDep = scalaDep("org.scala-lang.modules", "scala-partest", versionProp = "partest") // Non-Scala dependencies: @@ -398,7 +398,7 @@ lazy val compiler = configureAsSubproject(project) description := "Scala Compiler", libraryDependencies ++= Seq(antDep, asmDep), // These are only needed for the POM: - libraryDependencies ++= Seq(scalaXmlDep, scalaParserCombinatorsDep, jlineDep % "optional"), + libraryDependencies ++= Seq(scalaXmlDep, jlineDep % "optional"), // this a way to make sure that classes from interactive and scaladoc projects // end up in compiler jar (that's what Ant build does) // we need to use LocalProject references (with strings) to deal with mutual recursion @@ -427,7 +427,6 @@ lazy val compiler = configureAsSubproject(project) Osgi.headers ++= Seq( "Import-Package" -> ("jline.*;resolution:=optional," + "org.apache.tools.ant.*;resolution:=optional," + - "scala.util.parsing.*;version=\"${range;[====,====];"+versionNumber("scala-parser-combinators")+"}\";resolution:=optional," + "scala.xml.*;version=\"${range;[====,====];"+versionNumber("scala-xml")+"}\";resolution:=optional," + "scala.*;version=\"${range;[==,=+);${ver}}\"," + "*"), @@ -521,7 +520,7 @@ lazy val scaladoc = configureAsSubproject(project) .settings( name := "scala-compiler-doc", description := "Scala Documentation Generator", - libraryDependencies ++= Seq(scalaXmlDep, scalaParserCombinatorsDep, partestDep), + libraryDependencies ++= Seq(scalaXmlDep, partestDep), includeFilter in unmanagedResources in Compile := "*.html" | "*.css" | "*.gif" | "*.png" | "*.js" | "*.txt" | "*.svg" | "*.eot" | "*.woff" | "*.ttf" ) .dependsOn(compiler) diff --git a/build.xml b/build.xml index 6b2c9ade0da4..7c6f525c1cf9 100644 --- a/build.xml +++ b/build.xml @@ -367,7 +367,7 @@ TODO: - + @@ -791,7 +791,6 @@ TODO: - @@ -804,7 +803,9 @@ TODO: - + + + @@ -913,8 +914,7 @@ TODO: + scala-xml via external-modules-nocore, as part of `partest.classpath` --> @@ -922,7 +922,6 @@ TODO: - @@ -1278,8 +1277,6 @@ TODO: --> - - diff --git a/dbuild-meta.json b/dbuild-meta.json index 4806f9fa5a9e..ca3ce2a1104b 100644 --- a/dbuild-meta.json +++ b/dbuild-meta.json @@ -48,11 +48,6 @@ "extension" : "jar", "name" : "scala-xml", "organization" : "org.scala-lang.modules" - }, - { - "extension" : "jar", - "name" : "scala-parser-combinators", - "organization" : "org.scala-lang.modules" } ], "name" : "scala-compiler", diff --git a/src/build/bnd/scala-compiler.bnd b/src/build/bnd/scala-compiler.bnd index 3e60c4973c8c..c12c84c3f944 100644 --- a/src/build/bnd/scala-compiler.bnd +++ b/src/build/bnd/scala-compiler.bnd @@ -5,7 +5,6 @@ Bundle-Version: ${ver} Export-Package: *;version=${ver} Import-Package: jline.*;resolution:=optional, \ org.apache.tools.ant.*;resolution:=optional, \ - scala.util.parsing.*;version="${range;[====,====];@PARSER_COMBINATORS_VERSION@}";resolution:=optional, \ scala.xml.*;version="${range;[====,====];@XML_VERSION@}";resolution:=optional, \ scala.*;version="${range;[==,=+);${ver}}", \ * diff --git a/src/build/dbuild-meta-json-gen.scala b/src/build/dbuild-meta-json-gen.scala index 043ad19b2e70..6405650d881c 100644 --- a/src/build/dbuild-meta-json-gen.scala +++ b/src/build/dbuild-meta-json-gen.scala @@ -23,8 +23,7 @@ val meta = Project("scala-compiler", "org.scala-lang", Seq(ProjectRef("scala-compiler", "org.scala-lang")), Seq(ProjectRef("scala-reflect", "org.scala-lang"), - ProjectRef("scala-xml", "org.scala-lang.modules"), - ProjectRef("scala-parser-combinators", "org.scala-lang.modules") + ProjectRef("scala-xml", "org.scala-lang.modules") )), // Project("scala-repl", "org.scala-lang", @@ -37,7 +36,7 @@ val meta = // Project("scaladoc", "org.scala-lang", // Seq(ProjectRef("scaladoc", "org.scala-lang")), - // Seq(ProjectRef("scala-compiler", "org.scala-lang"),ProjectRef("scala-partest", "org.scala-lang"), ProjectRef("scala-xml", "org.scala-lang"), ProjectRef("scala-parser-combinators", "org.scala-lang"))), + // Seq(ProjectRef("scala-compiler", "org.scala-lang"),ProjectRef("scala-partest", "org.scala-lang"), ProjectRef("scala-xml", "org.scala-lang"))), Project("scalap", "org.scala-lang", Seq(ProjectRef("scalap", "org.scala-lang")), diff --git a/src/build/maven/scala-compiler-doc-pom.xml b/src/build/maven/scala-compiler-doc-pom.xml index 0c33d23d6150..86ca3f865baa 100644 --- a/src/build/maven/scala-compiler-doc-pom.xml +++ b/src/build/maven/scala-compiler-doc-pom.xml @@ -39,11 +39,6 @@ scala-xml_@SCALA_BINARY_VERSION@ @XML_VERSION@
- - org.scala-lang.modules - scala-parser-combinators_@SCALA_BINARY_VERSION@ - @PARSER_COMBINATORS_VERSION@ - diff --git a/src/build/maven/scala-compiler-pom.xml b/src/build/maven/scala-compiler-pom.xml index 15546109c8e3..9c157d17d97e 100644 --- a/src/build/maven/scala-compiler-pom.xml +++ b/src/build/maven/scala-compiler-pom.xml @@ -45,11 +45,6 @@ scala-xml_@SCALA_BINARY_VERSION@ @XML_VERSION@ - - org.scala-lang.modules - scala-parser-combinators_@SCALA_BINARY_VERSION@ - @PARSER_COMBINATORS_VERSION@ - jline jline diff --git a/src/eclipse/interactive/.classpath b/src/eclipse/interactive/.classpath index 721351a20775..9c02e9bb1aab 100644 --- a/src/eclipse/interactive/.classpath +++ b/src/eclipse/interactive/.classpath @@ -1,7 +1,7 @@ - + diff --git a/src/eclipse/partest/.classpath b/src/eclipse/partest/.classpath index 22afd65d439f..74eb47032dd0 100644 --- a/src/eclipse/partest/.classpath +++ b/src/eclipse/partest/.classpath @@ -1,7 +1,7 @@ - + @@ -9,6 +9,6 @@ - + diff --git a/src/eclipse/repl/.classpath b/src/eclipse/repl/.classpath index 141f84e6bb21..4b5369096254 100644 --- a/src/eclipse/repl/.classpath +++ b/src/eclipse/repl/.classpath @@ -1,7 +1,7 @@ - + diff --git a/src/eclipse/scala-compiler/.classpath b/src/eclipse/scala-compiler/.classpath index 625b9b2e4b8f..c4683059346b 100644 --- a/src/eclipse/scala-compiler/.classpath +++ b/src/eclipse/scala-compiler/.classpath @@ -4,7 +4,7 @@ - + diff --git a/src/eclipse/scaladoc/.classpath b/src/eclipse/scaladoc/.classpath index b4450df4ef19..9ae1a1c1dd41 100644 --- a/src/eclipse/scaladoc/.classpath +++ b/src/eclipse/scaladoc/.classpath @@ -2,12 +2,11 @@ - + - - - + + diff --git a/src/eclipse/test-junit/.classpath b/src/eclipse/test-junit/.classpath index 1e1b51066312..af112840b7d3 100644 --- a/src/eclipse/test-junit/.classpath +++ b/src/eclipse/test-junit/.classpath @@ -1,7 +1,7 @@ - + @@ -10,7 +10,7 @@ - + diff --git a/src/intellij/scala.ipr.SAMPLE b/src/intellij/scala.ipr.SAMPLE index 79ad2808f692..01f08c4efdc0 100644 --- a/src/intellij/scala.ipr.SAMPLE +++ b/src/intellij/scala.ipr.SAMPLE @@ -74,9 +74,8 @@ - - - + + @@ -86,9 +85,8 @@ - - - + + @@ -97,14 +95,13 @@ - - - + + - + - + @@ -112,7 +109,7 @@ - + @@ -123,11 +120,10 @@ - - - + + - + @@ -136,7 +132,7 @@ - + @@ -145,9 +141,8 @@ - - - + + @@ -156,9 +151,8 @@ - - - + + @@ -259,10 +253,9 @@ - - - - + + + @@ -273,9 +266,8 @@ - - - + + @@ -284,12 +276,11 @@ @@ -300,11 +291,10 @@ - - - + + - + diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala index 6b24c0f5687c..8f58a7b84563 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala @@ -10,7 +10,6 @@ package page import scala.tools.nsc.doc import scala.tools.nsc.doc.model.{Package, DocTemplateEntity} import scala.tools.nsc.doc.html.{Page, HtmlFactory} -import scala.util.parsing.json.{JSONObject, JSONArray, JSONType} class IndexScript(universe: doc.Universe) extends Page { import model._ @@ -21,7 +20,7 @@ class IndexScript(universe: doc.Universe) extends Page { override def writeFor(site: HtmlFactory) { writeFile(site) { - _.write("Index.PACKAGES = " + packages.toString() + ";") + _.write(s"Index.PACKAGES = $packages;") } } @@ -30,7 +29,7 @@ class IndexScript(universe: doc.Universe) extends Page { case (pack, templates) => { val merged = mergeByQualifiedName(templates) - val ary = merged.keys.toList.sortBy(_.toLowerCase).map { key => + val ary = merged.keys.toVector.sortBy(_.toLowerCase).map { key => /** One pair is generated for the class/trait and one for the * companion object, both will have the same {"name": key} * @@ -44,7 +43,7 @@ class IndexScript(universe: doc.Universe) extends Page { Seq( kind -> relativeLinkTo(t), "kind" -> kind, - s"members_$kind" -> membersToJSON(t.members.filter(!_.isShadowedOrAmbiguousImplicit), t), + s"members_$kind" -> membersToJSON(t.members.toVector.filter(!_.isShadowedOrAmbiguousImplicit), t), "shortDescription" -> shortDesc(t)) } @@ -58,18 +57,18 @@ class IndexScript(universe: doc.Universe) extends Page { JSONObject(Map(pairs : _*)) } - def mergeByQualifiedName(source: List[DocTemplateEntity]) = { - var result = Map[String, List[DocTemplateEntity]]() + private def mergeByQualifiedName(source: List[DocTemplateEntity]): collection.mutable.Map[String, List[DocTemplateEntity]] = { + val result = collection.mutable.Map[String, List[DocTemplateEntity]]() for (t <- source) { val k = t.qualifiedName - result += k -> (result.getOrElse(k, List()) :+ t) + result += k -> (result.getOrElse(k, Nil) :+ t) } result } - def allPackages = { + def allPackages: List[Package] = { def f(parent: Package): List[Package] = { parent.packages.flatMap( p => f(p) :+ p @@ -78,7 +77,7 @@ class IndexScript(universe: doc.Universe) extends Page { f(universe.rootPackage).sortBy(_.toString) } - def allPackagesWithTemplates = { + def allPackagesWithTemplates: Map[Package, List[DocTemplateEntity]] = { Map(allPackages.map((key) => { key -> key.templates.collect { case t: DocTemplateEntity if !t.isPackage && !universe.settings.hardcoded.isExcluded(t.qualifiedName) => t @@ -92,8 +91,8 @@ class IndexScript(universe: doc.Universe) extends Page { } /** Returns the json representation of the supplied members */ - def membersToJSON(entities: List[MemberEntity], parent: DocTemplateEntity): JSONType = - JSONArray(entities map (memberToJSON(_, parent))) + def membersToJSON(entities: Vector[MemberEntity], parent: DocTemplateEntity): JSONArray = + JSONArray(entities.map(memberToJSON(_, parent))) private def memberToJSON(mbr: MemberEntity, parent: DocTemplateEntity): JSONObject = { /** This function takes a member and gets eventual parameters and the diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/JSON.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/JSON.scala new file mode 100644 index 000000000000..5f6cb7e7995d --- /dev/null +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/JSON.scala @@ -0,0 +1,56 @@ +package scala.tools.nsc.doc.html.page + +import JSONFormat.format + +private[page] object JSONFormat { + + def format(x: Any): String = x match { + case s: String => s"""\"${quoteString(s)}\"""" + case jo: JSONObject => jo.toString + case ja: JSONArray => ja.toString + case other => throw new UnsupportedOperationException(s"Value $other of class ${other.getClass} cannot be formatted.") + } + + /** This function can be used to properly quote Strings for JSON output. */ + def quoteString(s: String): String = { + val len: Int = s.length + val buf = new StringBuilder(len + len/4) + var i: Int = 0 + while (i < len) { + s.apply(i) match { + case '"' => buf ++= "\\\"" + case '\\' => buf ++= "\\\\" + case '/' => buf ++= "\\/" + case '\b' => buf ++= "\\b" + case '\f' => buf ++= "\\f" + case '\n' => buf ++= "\\n" + case '\r' => buf ++= "\\r" + case '\t' => buf ++= "\\t" + /* We'll unicode escape any control characters. These include: + * 0x00 -> 0x1f : ASCII Control (C0 Control Codes) + * 0x7f : ASCII DELETE + * 0x80 -> 0x9f : C1 Control Codes + * + * Per RFC4627, section 2.5, we're not technically required to + * encode the C1 codes, but we do to be safe. + */ + case c if ((c >= '\u0000' && c <= '\u001f') || (c >= '\u007f' && c <= '\u009f')) => + val cint = c.toInt + buf ++= f"\\u$cint%04x" + case c => buf += c + } + i += 1 + } + buf.toString() + } +} + +/** Represents a JSON Object (map). */ +private[page] case class JSONObject(obj: Map[String,Any]) { + override def toString = obj.map({ case (k,v) => format(k) + " : " + format(v) }).mkString("{", ", ", "}") +} + +/** Represents a JSON Array (vector). */ +private[page] case class JSONArray(vector: Vector[Any]) { + override def toString = vector.map(format).mkString("[", ", ", "]") +} From e4a978d06b410700b2ee85696b9ad6f6aa7ff183 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 22 Jul 2016 14:19:19 +1000 Subject: [PATCH 148/153] SD-121 Remove now-unneeded J{Function,Proc}N functional interfaces Non specialized functions can directly use `scala.FunctionN` as the functional interface, now that mixin generates default methods in the new trait encoding. Unfortunately we can't do this for specialized functions as things stand: specialization leaves the wrong method abstract. In principle, we could/should amend the specialization transform to fix this. But my earlier attempts at this weren't sucessful, so for now we have to stick with the fallback plan of keeping some hand rolled functional interfaces around. This commit reduces the surface area of `scala.runtime.java8` to the minimal requiremnt: one functional interface for each specialized variant of `Function{0,1,2}`. --- .../tools/nsc/transform/Delambdafy.scala | 8 +- .../scala/runtime/java8/JFunction.java | 146 ----- .../runtime/java8/JFunction0$mcB$sp.java | 2 +- .../runtime/java8/JFunction0$mcC$sp.java | 2 +- .../runtime/java8/JFunction0$mcD$sp.java | 2 +- .../runtime/java8/JFunction0$mcF$sp.java | 2 +- .../runtime/java8/JFunction0$mcI$sp.java | 2 +- .../runtime/java8/JFunction0$mcJ$sp.java | 2 +- .../runtime/java8/JFunction0$mcS$sp.java | 2 +- .../runtime/java8/JFunction0$mcV$sp.java | 2 +- .../runtime/java8/JFunction0$mcZ$sp.java | 2 +- .../scala/runtime/java8/JFunction0.java | 39 -- .../runtime/java8/JFunction1$mcDD$sp.java | 2 +- .../runtime/java8/JFunction1$mcDF$sp.java | 2 +- .../runtime/java8/JFunction1$mcDI$sp.java | 2 +- .../runtime/java8/JFunction1$mcDJ$sp.java | 2 +- .../runtime/java8/JFunction1$mcFD$sp.java | 2 +- .../runtime/java8/JFunction1$mcFF$sp.java | 2 +- .../runtime/java8/JFunction1$mcFI$sp.java | 2 +- .../runtime/java8/JFunction1$mcFJ$sp.java | 2 +- .../runtime/java8/JFunction1$mcID$sp.java | 2 +- .../runtime/java8/JFunction1$mcIF$sp.java | 2 +- .../runtime/java8/JFunction1$mcII$sp.java | 2 +- .../runtime/java8/JFunction1$mcIJ$sp.java | 2 +- .../runtime/java8/JFunction1$mcJD$sp.java | 2 +- .../runtime/java8/JFunction1$mcJF$sp.java | 2 +- .../runtime/java8/JFunction1$mcJI$sp.java | 2 +- .../runtime/java8/JFunction1$mcJJ$sp.java | 2 +- .../runtime/java8/JFunction1$mcVD$sp.java | 2 +- .../runtime/java8/JFunction1$mcVF$sp.java | 2 +- .../runtime/java8/JFunction1$mcVI$sp.java | 2 +- .../runtime/java8/JFunction1$mcVJ$sp.java | 2 +- .../runtime/java8/JFunction1$mcZD$sp.java | 2 +- .../runtime/java8/JFunction1$mcZF$sp.java | 2 +- .../runtime/java8/JFunction1$mcZI$sp.java | 2 +- .../runtime/java8/JFunction1$mcZJ$sp.java | 2 +- .../scala/runtime/java8/JFunction1.java | 228 -------- .../scala/runtime/java8/JFunction10.java | 10 - .../scala/runtime/java8/JFunction11.java | 10 - .../scala/runtime/java8/JFunction12.java | 10 - .../scala/runtime/java8/JFunction13.java | 10 - .../scala/runtime/java8/JFunction14.java | 10 - .../scala/runtime/java8/JFunction15.java | 10 - .../scala/runtime/java8/JFunction16.java | 10 - .../scala/runtime/java8/JFunction17.java | 10 - .../scala/runtime/java8/JFunction18.java | 10 - .../scala/runtime/java8/JFunction19.java | 10 - .../runtime/java8/JFunction2$mcDDD$sp.java | 2 +- .../runtime/java8/JFunction2$mcDDI$sp.java | 2 +- .../runtime/java8/JFunction2$mcDDJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcDID$sp.java | 2 +- .../runtime/java8/JFunction2$mcDII$sp.java | 2 +- .../runtime/java8/JFunction2$mcDIJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcDJD$sp.java | 2 +- .../runtime/java8/JFunction2$mcDJI$sp.java | 2 +- .../runtime/java8/JFunction2$mcDJJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcFDD$sp.java | 2 +- .../runtime/java8/JFunction2$mcFDI$sp.java | 2 +- .../runtime/java8/JFunction2$mcFDJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcFID$sp.java | 2 +- .../runtime/java8/JFunction2$mcFII$sp.java | 2 +- .../runtime/java8/JFunction2$mcFIJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcFJD$sp.java | 2 +- .../runtime/java8/JFunction2$mcFJI$sp.java | 2 +- .../runtime/java8/JFunction2$mcFJJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcIDD$sp.java | 2 +- .../runtime/java8/JFunction2$mcIDI$sp.java | 2 +- .../runtime/java8/JFunction2$mcIDJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcIID$sp.java | 2 +- .../runtime/java8/JFunction2$mcIII$sp.java | 2 +- .../runtime/java8/JFunction2$mcIIJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcIJD$sp.java | 2 +- .../runtime/java8/JFunction2$mcIJI$sp.java | 2 +- .../runtime/java8/JFunction2$mcIJJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcJDD$sp.java | 2 +- .../runtime/java8/JFunction2$mcJDI$sp.java | 2 +- .../runtime/java8/JFunction2$mcJDJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcJID$sp.java | 2 +- .../runtime/java8/JFunction2$mcJII$sp.java | 2 +- .../runtime/java8/JFunction2$mcJIJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcJJD$sp.java | 2 +- .../runtime/java8/JFunction2$mcJJI$sp.java | 2 +- .../runtime/java8/JFunction2$mcJJJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcVDD$sp.java | 2 +- .../runtime/java8/JFunction2$mcVDI$sp.java | 2 +- .../runtime/java8/JFunction2$mcVDJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcVID$sp.java | 2 +- .../runtime/java8/JFunction2$mcVII$sp.java | 2 +- .../runtime/java8/JFunction2$mcVIJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcVJD$sp.java | 2 +- .../runtime/java8/JFunction2$mcVJI$sp.java | 2 +- .../runtime/java8/JFunction2$mcVJJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcZDD$sp.java | 2 +- .../runtime/java8/JFunction2$mcZDI$sp.java | 2 +- .../runtime/java8/JFunction2$mcZDJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcZID$sp.java | 2 +- .../runtime/java8/JFunction2$mcZII$sp.java | 2 +- .../runtime/java8/JFunction2$mcZIJ$sp.java | 2 +- .../runtime/java8/JFunction2$mcZJD$sp.java | 2 +- .../runtime/java8/JFunction2$mcZJI$sp.java | 2 +- .../runtime/java8/JFunction2$mcZJJ$sp.java | 2 +- .../scala/runtime/java8/JFunction2.java | 498 ------------------ .../scala/runtime/java8/JFunction20.java | 10 - .../scala/runtime/java8/JFunction21.java | 10 - .../scala/runtime/java8/JFunction22.java | 10 - .../scala/runtime/java8/JFunction3.java | 10 - .../scala/runtime/java8/JFunction4.java | 10 - .../scala/runtime/java8/JFunction5.java | 10 - .../scala/runtime/java8/JFunction6.java | 10 - .../scala/runtime/java8/JFunction7.java | 10 - .../scala/runtime/java8/JFunction8.java | 10 - .../scala/runtime/java8/JFunction9.java | 10 - .../scala/runtime/java8/JProcedure0.java | 21 - .../scala/runtime/java8/JProcedure1.java | 21 - .../scala/runtime/java8/JProcedure10.java | 21 - .../scala/runtime/java8/JProcedure11.java | 21 - .../scala/runtime/java8/JProcedure12.java | 21 - .../scala/runtime/java8/JProcedure13.java | 21 - .../scala/runtime/java8/JProcedure14.java | 21 - .../scala/runtime/java8/JProcedure15.java | 21 - .../scala/runtime/java8/JProcedure16.java | 21 - .../scala/runtime/java8/JProcedure17.java | 21 - .../scala/runtime/java8/JProcedure18.java | 21 - .../scala/runtime/java8/JProcedure19.java | 21 - .../scala/runtime/java8/JProcedure2.java | 21 - .../scala/runtime/java8/JProcedure20.java | 21 - .../scala/runtime/java8/JProcedure21.java | 21 - .../scala/runtime/java8/JProcedure22.java | 21 - .../scala/runtime/java8/JProcedure3.java | 21 - .../scala/runtime/java8/JProcedure4.java | 21 - .../scala/runtime/java8/JProcedure5.java | 21 - .../scala/runtime/java8/JProcedure6.java | 21 - .../scala/runtime/java8/JProcedure7.java | 21 - .../scala/runtime/java8/JProcedure8.java | 21 - .../scala/runtime/java8/JProcedure9.java | 21 - 135 files changed, 93 insertions(+), 1683 deletions(-) delete mode 100644 src/library/scala/runtime/java8/JFunction.java delete mode 100644 src/library/scala/runtime/java8/JFunction0.java delete mode 100644 src/library/scala/runtime/java8/JFunction1.java delete mode 100644 src/library/scala/runtime/java8/JFunction10.java delete mode 100644 src/library/scala/runtime/java8/JFunction11.java delete mode 100644 src/library/scala/runtime/java8/JFunction12.java delete mode 100644 src/library/scala/runtime/java8/JFunction13.java delete mode 100644 src/library/scala/runtime/java8/JFunction14.java delete mode 100644 src/library/scala/runtime/java8/JFunction15.java delete mode 100644 src/library/scala/runtime/java8/JFunction16.java delete mode 100644 src/library/scala/runtime/java8/JFunction17.java delete mode 100644 src/library/scala/runtime/java8/JFunction18.java delete mode 100644 src/library/scala/runtime/java8/JFunction19.java delete mode 100644 src/library/scala/runtime/java8/JFunction2.java delete mode 100644 src/library/scala/runtime/java8/JFunction20.java delete mode 100644 src/library/scala/runtime/java8/JFunction21.java delete mode 100644 src/library/scala/runtime/java8/JFunction22.java delete mode 100644 src/library/scala/runtime/java8/JFunction3.java delete mode 100644 src/library/scala/runtime/java8/JFunction4.java delete mode 100644 src/library/scala/runtime/java8/JFunction5.java delete mode 100644 src/library/scala/runtime/java8/JFunction6.java delete mode 100644 src/library/scala/runtime/java8/JFunction7.java delete mode 100644 src/library/scala/runtime/java8/JFunction8.java delete mode 100644 src/library/scala/runtime/java8/JFunction9.java delete mode 100644 src/library/scala/runtime/java8/JProcedure0.java delete mode 100644 src/library/scala/runtime/java8/JProcedure1.java delete mode 100644 src/library/scala/runtime/java8/JProcedure10.java delete mode 100644 src/library/scala/runtime/java8/JProcedure11.java delete mode 100644 src/library/scala/runtime/java8/JProcedure12.java delete mode 100644 src/library/scala/runtime/java8/JProcedure13.java delete mode 100644 src/library/scala/runtime/java8/JProcedure14.java delete mode 100644 src/library/scala/runtime/java8/JProcedure15.java delete mode 100644 src/library/scala/runtime/java8/JProcedure16.java delete mode 100644 src/library/scala/runtime/java8/JProcedure17.java delete mode 100644 src/library/scala/runtime/java8/JProcedure18.java delete mode 100644 src/library/scala/runtime/java8/JProcedure19.java delete mode 100644 src/library/scala/runtime/java8/JProcedure2.java delete mode 100644 src/library/scala/runtime/java8/JProcedure20.java delete mode 100644 src/library/scala/runtime/java8/JProcedure21.java delete mode 100644 src/library/scala/runtime/java8/JProcedure22.java delete mode 100644 src/library/scala/runtime/java8/JProcedure3.java delete mode 100644 src/library/scala/runtime/java8/JProcedure4.java delete mode 100644 src/library/scala/runtime/java8/JProcedure5.java delete mode 100644 src/library/scala/runtime/java8/JProcedure6.java delete mode 100644 src/library/scala/runtime/java8/JProcedure7.java delete mode 100644 src/library/scala/runtime/java8/JProcedure8.java delete mode 100644 src/library/scala/runtime/java8/JProcedure9.java diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 804bcddb7b88..88837842fa3b 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -241,8 +241,12 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre exitingErasure(target.info.paramTypes).map(reboxValueClass) :+ reboxValueClass(exitingErasure(target.info.resultType))).toTypeName val isSpecialized = specializedName != funSym.name - val functionalInterface = // TODO: this is no longer needed, right? we can just use the regular function classes - if (isSpecialized) currentRun.runDefinitions.Scala_Java8_CompatPackage.info.decl(specializedName.prepend("J")) + val functionalInterface = + if (isSpecialized) { + // Unfortunately we still need to use custom functional interfaces for specialized functions so that the + // unboxed apply method is left abstract for us to implement. + currentRun.runDefinitions.Scala_Java8_CompatPackage.info.decl(specializedName.prepend("J")) + } else FunctionClass(originalFunction.vparams.length) (functionalInterface, isSpecialized) diff --git a/src/library/scala/runtime/java8/JFunction.java b/src/library/scala/runtime/java8/JFunction.java deleted file mode 100644 index 326aad3fecc9..000000000000 --- a/src/library/scala/runtime/java8/JFunction.java +++ /dev/null @@ -1,146 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -public final class JFunction { - private JFunction() {} - public static scala.Function0 func(JFunction0 f) { return f; } - public static scala.Function0 proc(JProcedure0 p) { return p; } - public static scala.Function0 procSpecialized(JFunction0$mcV$sp f) { return f; } - public static scala.Function0 funcSpecialized(JFunction0$mcB$sp f) { return f; } - public static scala.Function0 funcSpecialized(JFunction0$mcS$sp f) { return f; } - public static scala.Function0 funcSpecialized(JFunction0$mcI$sp f) { return f; } - public static scala.Function0 funcSpecialized(JFunction0$mcJ$sp f) { return f; } - public static scala.Function0 funcSpecialized(JFunction0$mcC$sp f) { return f; } - public static scala.Function0 funcSpecialized(JFunction0$mcF$sp f) { return f; } - public static scala.Function0 funcSpecialized(JFunction0$mcD$sp f) { return f; } - public static scala.Function0 funcSpecialized(JFunction0$mcZ$sp f) { return f; } - public static scala.Function1 func(JFunction1 f) { return f; } - public static scala.Function1 proc(JProcedure1 p) { return p; } - public static scala.Function1 procSpecialized(JFunction1$mcVI$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcZI$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcII$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcFI$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcJI$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcDI$sp f) { return f; } - public static scala.Function1 procSpecialized(JFunction1$mcVJ$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcZJ$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcIJ$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcFJ$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcJJ$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcDJ$sp f) { return f; } - public static scala.Function1 procSpecialized(JFunction1$mcVF$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcZF$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcIF$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcFF$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcJF$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcDF$sp f) { return f; } - public static scala.Function1 procSpecialized(JFunction1$mcVD$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcZD$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcID$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcFD$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcJD$sp f) { return f; } - public static scala.Function1 funcSpecialized(JFunction1$mcDD$sp f) { return f; } - public static scala.Function2 func(JFunction2 f) { return f; } - public static scala.Function2 proc(JProcedure2 p) { return p; } - public static scala.Function2 procSpecialized(JFunction2$mcVII$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZII$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIII$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFII$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJII$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDII$sp f) { return f; } - public static scala.Function2 procSpecialized(JFunction2$mcVIJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZIJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIIJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFIJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJIJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDIJ$sp f) { return f; } - public static scala.Function2 procSpecialized(JFunction2$mcVID$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZID$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIID$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFID$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJID$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDID$sp f) { return f; } - public static scala.Function2 procSpecialized(JFunction2$mcVJI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZJI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIJI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFJI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJJI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDJI$sp f) { return f; } - public static scala.Function2 procSpecialized(JFunction2$mcVJJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZJJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIJJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFJJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJJJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDJJ$sp f) { return f; } - public static scala.Function2 procSpecialized(JFunction2$mcVJD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZJD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIJD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFJD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJJD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDJD$sp f) { return f; } - public static scala.Function2 procSpecialized(JFunction2$mcVDI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZDI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIDI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFDI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJDI$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDDI$sp f) { return f; } - public static scala.Function2 procSpecialized(JFunction2$mcVDJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZDJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIDJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFDJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJDJ$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDDJ$sp f) { return f; } - public static scala.Function2 procSpecialized(JFunction2$mcVDD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcZDD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcIDD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcFDD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcJDD$sp f) { return f; } - public static scala.Function2 funcSpecialized(JFunction2$mcDDD$sp f) { return f; } - public static scala.Function3 func(JFunction3 f) { return f; } - public static scala.Function3 proc(JProcedure3 p) { return p; } - public static scala.Function4 func(JFunction4 f) { return f; } - public static scala.Function4 proc(JProcedure4 p) { return p; } - public static scala.Function5 func(JFunction5 f) { return f; } - public static scala.Function5 proc(JProcedure5 p) { return p; } - public static scala.Function6 func(JFunction6 f) { return f; } - public static scala.Function6 proc(JProcedure6 p) { return p; } - public static scala.Function7 func(JFunction7 f) { return f; } - public static scala.Function7 proc(JProcedure7 p) { return p; } - public static scala.Function8 func(JFunction8 f) { return f; } - public static scala.Function8 proc(JProcedure8 p) { return p; } - public static scala.Function9 func(JFunction9 f) { return f; } - public static scala.Function9 proc(JProcedure9 p) { return p; } - public static scala.Function10 func(JFunction10 f) { return f; } - public static scala.Function10 proc(JProcedure10 p) { return p; } - public static scala.Function11 func(JFunction11 f) { return f; } - public static scala.Function11 proc(JProcedure11 p) { return p; } - public static scala.Function12 func(JFunction12 f) { return f; } - public static scala.Function12 proc(JProcedure12 p) { return p; } - public static scala.Function13 func(JFunction13 f) { return f; } - public static scala.Function13 proc(JProcedure13 p) { return p; } - public static scala.Function14 func(JFunction14 f) { return f; } - public static scala.Function14 proc(JProcedure14 p) { return p; } - public static scala.Function15 func(JFunction15 f) { return f; } - public static scala.Function15 proc(JProcedure15 p) { return p; } - public static scala.Function16 func(JFunction16 f) { return f; } - public static scala.Function16 proc(JProcedure16 p) { return p; } - public static scala.Function17 func(JFunction17 f) { return f; } - public static scala.Function17 proc(JProcedure17 p) { return p; } - public static scala.Function18 func(JFunction18 f) { return f; } - public static scala.Function18 proc(JProcedure18 p) { return p; } - public static scala.Function19 func(JFunction19 f) { return f; } - public static scala.Function19 proc(JProcedure19 p) { return p; } - public static scala.Function20 func(JFunction20 f) { return f; } - public static scala.Function20 proc(JProcedure20 p) { return p; } - public static scala.Function21 func(JFunction21 f) { return f; } - public static scala.Function21 proc(JProcedure21 p) { return p; } - public static scala.Function22 func(JFunction22 f) { return f; } - public static scala.Function22 proc(JProcedure22 p) { return p; } -} - diff --git a/src/library/scala/runtime/java8/JFunction0$mcB$sp.java b/src/library/scala/runtime/java8/JFunction0$mcB$sp.java index c88275763001..622dbabcf111 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcB$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcB$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcB$sp extends JFunction0 { +public interface JFunction0$mcB$sp extends scala.Function0, java.io.Serializable { byte apply$mcB$sp(); default Object apply() { return scala.runtime.BoxesRunTime.boxToByte(apply$mcB$sp()); } diff --git a/src/library/scala/runtime/java8/JFunction0$mcC$sp.java b/src/library/scala/runtime/java8/JFunction0$mcC$sp.java index c804529f718b..ad9a14ffa8fc 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcC$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcC$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcC$sp extends JFunction0 { +public interface JFunction0$mcC$sp extends scala.Function0, java.io.Serializable { char apply$mcC$sp(); default Object apply() { return scala.runtime.BoxesRunTime.boxToCharacter(apply$mcC$sp()); } diff --git a/src/library/scala/runtime/java8/JFunction0$mcD$sp.java b/src/library/scala/runtime/java8/JFunction0$mcD$sp.java index dacf50237c5b..291b50db4bd0 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcD$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcD$sp extends JFunction0 { +public interface JFunction0$mcD$sp extends scala.Function0, java.io.Serializable { double apply$mcD$sp(); default Object apply() { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcD$sp()); } diff --git a/src/library/scala/runtime/java8/JFunction0$mcF$sp.java b/src/library/scala/runtime/java8/JFunction0$mcF$sp.java index 2a9f8249246e..73b31dea0f0f 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcF$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcF$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcF$sp extends JFunction0 { +public interface JFunction0$mcF$sp extends scala.Function0, java.io.Serializable { float apply$mcF$sp(); default Object apply() { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcF$sp()); } diff --git a/src/library/scala/runtime/java8/JFunction0$mcI$sp.java b/src/library/scala/runtime/java8/JFunction0$mcI$sp.java index 75c612f9165f..f9b2d659ad31 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcI$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcI$sp extends JFunction0 { +public interface JFunction0$mcI$sp extends scala.Function0, java.io.Serializable { int apply$mcI$sp(); default Object apply() { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcI$sp()); } diff --git a/src/library/scala/runtime/java8/JFunction0$mcJ$sp.java b/src/library/scala/runtime/java8/JFunction0$mcJ$sp.java index d08984c794cc..73c41976b7a3 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcJ$sp extends JFunction0 { +public interface JFunction0$mcJ$sp extends scala.Function0, java.io.Serializable { long apply$mcJ$sp(); default Object apply() { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJ$sp()); } diff --git a/src/library/scala/runtime/java8/JFunction0$mcS$sp.java b/src/library/scala/runtime/java8/JFunction0$mcS$sp.java index d9e36a39f0c0..5fbabb2358e2 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcS$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcS$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcS$sp extends JFunction0 { +public interface JFunction0$mcS$sp extends scala.Function0, java.io.Serializable { short apply$mcS$sp(); default Object apply() { return scala.runtime.BoxesRunTime.boxToShort(apply$mcS$sp()); } diff --git a/src/library/scala/runtime/java8/JFunction0$mcV$sp.java b/src/library/scala/runtime/java8/JFunction0$mcV$sp.java index abd5e6ebbe47..735843796ce8 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcV$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcV$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcV$sp extends JFunction0 { +public interface JFunction0$mcV$sp extends scala.Function0, java.io.Serializable { void apply$mcV$sp(); default Object apply() { apply$mcV$sp(); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction0$mcZ$sp.java b/src/library/scala/runtime/java8/JFunction0$mcZ$sp.java index e1cd62a913b9..01234c1728a2 100644 --- a/src/library/scala/runtime/java8/JFunction0$mcZ$sp.java +++ b/src/library/scala/runtime/java8/JFunction0$mcZ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction0$mcZ$sp extends JFunction0 { +public interface JFunction0$mcZ$sp extends scala.Function0, java.io.Serializable { boolean apply$mcZ$sp(); default Object apply() { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZ$sp()); } diff --git a/src/library/scala/runtime/java8/JFunction0.java b/src/library/scala/runtime/java8/JFunction0.java deleted file mode 100644 index 13426cc8af61..000000000000 --- a/src/library/scala/runtime/java8/JFunction0.java +++ /dev/null @@ -1,39 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction0 extends scala.Function0, java.io.Serializable { - default void $init$() { - }; - default void apply$mcV$sp() { - apply(); - } - default byte apply$mcB$sp() { - return scala.runtime.BoxesRunTime.unboxToByte(apply()); - } - default short apply$mcS$sp() { - return scala.runtime.BoxesRunTime.unboxToShort(apply()); - } - default int apply$mcI$sp() { - return scala.runtime.BoxesRunTime.unboxToInt(apply()); - } - default long apply$mcJ$sp() { - return scala.runtime.BoxesRunTime.unboxToLong(apply()); - } - default char apply$mcC$sp() { - return scala.runtime.BoxesRunTime.unboxToChar(apply()); - } - default float apply$mcF$sp() { - return scala.runtime.BoxesRunTime.unboxToFloat(apply()); - } - default double apply$mcD$sp() { - return scala.runtime.BoxesRunTime.unboxToDouble(apply()); - } - default boolean apply$mcZ$sp() { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply()); - } -} diff --git a/src/library/scala/runtime/java8/JFunction1$mcDD$sp.java b/src/library/scala/runtime/java8/JFunction1$mcDD$sp.java index 4fbb370b8bff..07b85eed59a9 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcDD$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcDD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcDD$sp extends JFunction1 { +public interface JFunction1$mcDD$sp extends scala.Function1, java.io.Serializable { double apply$mcDD$sp(double v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDD$sp(scala.runtime.BoxesRunTime.unboxToDouble(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcDF$sp.java b/src/library/scala/runtime/java8/JFunction1$mcDF$sp.java index ce45666dd1d7..f09edd2ce25f 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcDF$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcDF$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcDF$sp extends JFunction1 { +public interface JFunction1$mcDF$sp extends scala.Function1, java.io.Serializable { double apply$mcDF$sp(float v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDF$sp(scala.runtime.BoxesRunTime.unboxToFloat(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcDI$sp.java b/src/library/scala/runtime/java8/JFunction1$mcDI$sp.java index 09cac947c967..3cf40cb74998 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcDI$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcDI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcDI$sp extends JFunction1 { +public interface JFunction1$mcDI$sp extends scala.Function1, java.io.Serializable { double apply$mcDI$sp(int v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDI$sp(scala.runtime.BoxesRunTime.unboxToInt(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcDJ$sp.java b/src/library/scala/runtime/java8/JFunction1$mcDJ$sp.java index f5154c3854e3..4023f30bc052 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcDJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcDJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcDJ$sp extends JFunction1 { +public interface JFunction1$mcDJ$sp extends scala.Function1, java.io.Serializable { double apply$mcDJ$sp(long v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDJ$sp(scala.runtime.BoxesRunTime.unboxToLong(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcFD$sp.java b/src/library/scala/runtime/java8/JFunction1$mcFD$sp.java index 758b432d99ba..d4608958383a 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcFD$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcFD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcFD$sp extends JFunction1 { +public interface JFunction1$mcFD$sp extends scala.Function1, java.io.Serializable { float apply$mcFD$sp(double v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFD$sp(scala.runtime.BoxesRunTime.unboxToDouble(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcFF$sp.java b/src/library/scala/runtime/java8/JFunction1$mcFF$sp.java index 7e13e287a51d..6c591800cadc 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcFF$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcFF$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcFF$sp extends JFunction1 { +public interface JFunction1$mcFF$sp extends scala.Function1, java.io.Serializable { float apply$mcFF$sp(float v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFF$sp(scala.runtime.BoxesRunTime.unboxToFloat(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcFI$sp.java b/src/library/scala/runtime/java8/JFunction1$mcFI$sp.java index e3c4a203c78a..666919591438 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcFI$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcFI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcFI$sp extends JFunction1 { +public interface JFunction1$mcFI$sp extends scala.Function1, java.io.Serializable { float apply$mcFI$sp(int v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFI$sp(scala.runtime.BoxesRunTime.unboxToInt(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcFJ$sp.java b/src/library/scala/runtime/java8/JFunction1$mcFJ$sp.java index d989fa1ea8e6..cd953677aec6 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcFJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcFJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcFJ$sp extends JFunction1 { +public interface JFunction1$mcFJ$sp extends scala.Function1, java.io.Serializable { float apply$mcFJ$sp(long v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFJ$sp(scala.runtime.BoxesRunTime.unboxToLong(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcID$sp.java b/src/library/scala/runtime/java8/JFunction1$mcID$sp.java index bde5d88d4636..37f686493681 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcID$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcID$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcID$sp extends JFunction1 { +public interface JFunction1$mcID$sp extends scala.Function1, java.io.Serializable { int apply$mcID$sp(double v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcID$sp(scala.runtime.BoxesRunTime.unboxToDouble(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcIF$sp.java b/src/library/scala/runtime/java8/JFunction1$mcIF$sp.java index d1d235aef111..8a7656a286d5 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcIF$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcIF$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcIF$sp extends JFunction1 { +public interface JFunction1$mcIF$sp extends scala.Function1, java.io.Serializable { int apply$mcIF$sp(float v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIF$sp(scala.runtime.BoxesRunTime.unboxToFloat(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcII$sp.java b/src/library/scala/runtime/java8/JFunction1$mcII$sp.java index ef44b3830cf3..792627b4005e 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcII$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcII$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcII$sp extends JFunction1 { +public interface JFunction1$mcII$sp extends scala.Function1, java.io.Serializable { int apply$mcII$sp(int v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcII$sp(scala.runtime.BoxesRunTime.unboxToInt(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcIJ$sp.java b/src/library/scala/runtime/java8/JFunction1$mcIJ$sp.java index 373d13cd46cf..01c47a67dac7 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcIJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcIJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcIJ$sp extends JFunction1 { +public interface JFunction1$mcIJ$sp extends scala.Function1, java.io.Serializable { int apply$mcIJ$sp(long v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIJ$sp(scala.runtime.BoxesRunTime.unboxToLong(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcJD$sp.java b/src/library/scala/runtime/java8/JFunction1$mcJD$sp.java index 86fd7b7779b1..d8d5274ca1db 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcJD$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcJD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcJD$sp extends JFunction1 { +public interface JFunction1$mcJD$sp extends scala.Function1, java.io.Serializable { long apply$mcJD$sp(double v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJD$sp(scala.runtime.BoxesRunTime.unboxToDouble(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcJF$sp.java b/src/library/scala/runtime/java8/JFunction1$mcJF$sp.java index 3bcf264034db..cc1fad36d04a 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcJF$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcJF$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcJF$sp extends JFunction1 { +public interface JFunction1$mcJF$sp extends scala.Function1, java.io.Serializable { long apply$mcJF$sp(float v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJF$sp(scala.runtime.BoxesRunTime.unboxToFloat(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcJI$sp.java b/src/library/scala/runtime/java8/JFunction1$mcJI$sp.java index 11bc15ef6e96..fe941dd61a7e 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcJI$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcJI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcJI$sp extends JFunction1 { +public interface JFunction1$mcJI$sp extends scala.Function1, java.io.Serializable { long apply$mcJI$sp(int v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJI$sp(scala.runtime.BoxesRunTime.unboxToInt(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcJJ$sp.java b/src/library/scala/runtime/java8/JFunction1$mcJJ$sp.java index 2e1ad7878fb9..7034115bad79 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcJJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcJJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcJJ$sp extends JFunction1 { +public interface JFunction1$mcJJ$sp extends scala.Function1, java.io.Serializable { long apply$mcJJ$sp(long v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJJ$sp(scala.runtime.BoxesRunTime.unboxToLong(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcVD$sp.java b/src/library/scala/runtime/java8/JFunction1$mcVD$sp.java index c8077e12680c..dde9f557226b 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcVD$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcVD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcVD$sp extends JFunction1 { +public interface JFunction1$mcVD$sp extends scala.Function1, java.io.Serializable { void apply$mcVD$sp(double v1); default Object apply(Object t) { apply$mcVD$sp(scala.runtime.BoxesRunTime.unboxToDouble(t)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction1$mcVF$sp.java b/src/library/scala/runtime/java8/JFunction1$mcVF$sp.java index e7be77f8e3d8..0ffd80621f13 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcVF$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcVF$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcVF$sp extends JFunction1 { +public interface JFunction1$mcVF$sp extends scala.Function1, java.io.Serializable { void apply$mcVF$sp(float v1); default Object apply(Object t) { apply$mcVF$sp(scala.runtime.BoxesRunTime.unboxToFloat(t)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction1$mcVI$sp.java b/src/library/scala/runtime/java8/JFunction1$mcVI$sp.java index 7597ca529451..2543d23e3134 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcVI$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcVI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcVI$sp extends JFunction1 { +public interface JFunction1$mcVI$sp extends scala.Function1, java.io.Serializable { void apply$mcVI$sp(int v1); default Object apply(Object t) { apply$mcVI$sp(scala.runtime.BoxesRunTime.unboxToInt(t)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction1$mcVJ$sp.java b/src/library/scala/runtime/java8/JFunction1$mcVJ$sp.java index 55c6c3997fc4..7564175402df 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcVJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcVJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcVJ$sp extends JFunction1 { +public interface JFunction1$mcVJ$sp extends scala.Function1, java.io.Serializable { void apply$mcVJ$sp(long v1); default Object apply(Object t) { apply$mcVJ$sp(scala.runtime.BoxesRunTime.unboxToLong(t)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction1$mcZD$sp.java b/src/library/scala/runtime/java8/JFunction1$mcZD$sp.java index 883a0e84fa94..ce5bd300297d 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcZD$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcZD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcZD$sp extends JFunction1 { +public interface JFunction1$mcZD$sp extends scala.Function1, java.io.Serializable { boolean apply$mcZD$sp(double v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZD$sp(scala.runtime.BoxesRunTime.unboxToDouble(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcZF$sp.java b/src/library/scala/runtime/java8/JFunction1$mcZF$sp.java index 884832ca37bd..baa691e5480f 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcZF$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcZF$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcZF$sp extends JFunction1 { +public interface JFunction1$mcZF$sp extends scala.Function1, java.io.Serializable { boolean apply$mcZF$sp(float v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZF$sp(scala.runtime.BoxesRunTime.unboxToFloat(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcZI$sp.java b/src/library/scala/runtime/java8/JFunction1$mcZI$sp.java index 8a51aa99a2a1..bf04b5922b93 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcZI$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcZI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcZI$sp extends JFunction1 { +public interface JFunction1$mcZI$sp extends scala.Function1, java.io.Serializable { boolean apply$mcZI$sp(int v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZI$sp(scala.runtime.BoxesRunTime.unboxToInt(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1$mcZJ$sp.java b/src/library/scala/runtime/java8/JFunction1$mcZJ$sp.java index dc619666dcbc..808eea87b8c7 100644 --- a/src/library/scala/runtime/java8/JFunction1$mcZJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction1$mcZJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction1$mcZJ$sp extends JFunction1 { +public interface JFunction1$mcZJ$sp extends scala.Function1, java.io.Serializable { boolean apply$mcZJ$sp(long v1); default Object apply(Object t) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZJ$sp(scala.runtime.BoxesRunTime.unboxToLong(t))); } diff --git a/src/library/scala/runtime/java8/JFunction1.java b/src/library/scala/runtime/java8/JFunction1.java deleted file mode 100644 index e1f886dad748..000000000000 --- a/src/library/scala/runtime/java8/JFunction1.java +++ /dev/null @@ -1,228 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction1 extends scala.Function1, java.io.Serializable { - default void apply$mcVI$sp(int v1) { - apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1)); - } - default boolean apply$mcZI$sp(int v1) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1))); - } - default int apply$mcII$sp(int v1) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1))); - } - default float apply$mcFI$sp(int v1) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1))); - } - default long apply$mcJI$sp(int v1) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1))); - } - default double apply$mcDI$sp(int v1) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1))); - } - default void apply$mcVJ$sp(long v1) { - apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1)); - } - default boolean apply$mcZJ$sp(long v1) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1))); - } - default int apply$mcIJ$sp(long v1) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1))); - } - default float apply$mcFJ$sp(long v1) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1))); - } - default long apply$mcJJ$sp(long v1) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1))); - } - default double apply$mcDJ$sp(long v1) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1))); - } - default void apply$mcVF$sp(float v1) { - apply((T1) scala.runtime.BoxesRunTime.boxToFloat(v1)); - } - default boolean apply$mcZF$sp(float v1) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToFloat(v1))); - } - default int apply$mcIF$sp(float v1) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToFloat(v1))); - } - default float apply$mcFF$sp(float v1) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToFloat(v1))); - } - default long apply$mcJF$sp(float v1) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToFloat(v1))); - } - default double apply$mcDF$sp(float v1) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToFloat(v1))); - } - default void apply$mcVD$sp(double v1) { - apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1)); - } - default boolean apply$mcZD$sp(double v1) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1))); - } - default int apply$mcID$sp(double v1) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1))); - } - default float apply$mcFD$sp(double v1) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1))); - } - default long apply$mcJD$sp(double v1) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1))); - } - default double apply$mcDD$sp(double v1) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1))); - } - - default scala.Function1 compose$mcVI$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcZI$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcII$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcFI$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcJI$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcDI$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcVJ$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcZJ$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcIJ$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcFJ$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcJJ$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcDJ$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcVF$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcZF$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcIF$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcFF$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcJF$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcDF$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcVD$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcZD$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcID$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcFD$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcJD$sp(scala.Function1 g) { - return compose(g); - } - default scala.Function1 compose$mcDD$sp(scala.Function1 g) { - return compose(g); - } - - default scala.Function1 andThen$mcVI$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcZI$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcII$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcFI$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcJI$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcDI$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcVJ$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcZJ$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcIJ$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcFJ$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcJJ$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcDJ$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcVF$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcZF$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcIF$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcFF$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcJF$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcDF$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcVD$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcZD$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcID$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcFD$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcJD$sp(scala.Function1 g) { - return andThen(g); - } - default scala.Function1 andThen$mcDD$sp(scala.Function1 g) { - return andThen(g); - } -} diff --git a/src/library/scala/runtime/java8/JFunction10.java b/src/library/scala/runtime/java8/JFunction10.java deleted file mode 100644 index f7a25c0df2ae..000000000000 --- a/src/library/scala/runtime/java8/JFunction10.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction10 extends scala.Function10, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction11.java b/src/library/scala/runtime/java8/JFunction11.java deleted file mode 100644 index 9a548b8fc990..000000000000 --- a/src/library/scala/runtime/java8/JFunction11.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction11 extends scala.Function11, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction12.java b/src/library/scala/runtime/java8/JFunction12.java deleted file mode 100644 index 12fb73faafba..000000000000 --- a/src/library/scala/runtime/java8/JFunction12.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction12 extends scala.Function12, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction13.java b/src/library/scala/runtime/java8/JFunction13.java deleted file mode 100644 index c85c63448ab5..000000000000 --- a/src/library/scala/runtime/java8/JFunction13.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction13 extends scala.Function13, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction14.java b/src/library/scala/runtime/java8/JFunction14.java deleted file mode 100644 index 9a578833aaad..000000000000 --- a/src/library/scala/runtime/java8/JFunction14.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction14 extends scala.Function14, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction15.java b/src/library/scala/runtime/java8/JFunction15.java deleted file mode 100644 index e993643953ce..000000000000 --- a/src/library/scala/runtime/java8/JFunction15.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction15 extends scala.Function15, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction16.java b/src/library/scala/runtime/java8/JFunction16.java deleted file mode 100644 index a252cb5303bd..000000000000 --- a/src/library/scala/runtime/java8/JFunction16.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction16 extends scala.Function16, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction17.java b/src/library/scala/runtime/java8/JFunction17.java deleted file mode 100644 index 045aa7196fa9..000000000000 --- a/src/library/scala/runtime/java8/JFunction17.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction17 extends scala.Function17, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction18.java b/src/library/scala/runtime/java8/JFunction18.java deleted file mode 100644 index ba2bf31206c1..000000000000 --- a/src/library/scala/runtime/java8/JFunction18.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction18 extends scala.Function18, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction19.java b/src/library/scala/runtime/java8/JFunction19.java deleted file mode 100644 index dde48242930f..000000000000 --- a/src/library/scala/runtime/java8/JFunction19.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction19 extends scala.Function19, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction2$mcDDD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDDD$sp.java index 1c11fb52522d..80ab5203d954 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDDD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDDD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDDD$sp extends JFunction2 { +public interface JFunction2$mcDDD$sp extends scala.Function2, java.io.Serializable { double apply$mcDDD$sp(double v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDDD$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcDDI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDDI$sp.java index e080bc87fa20..8e92338b825b 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDDI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDDI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDDI$sp extends JFunction2 { +public interface JFunction2$mcDDI$sp extends scala.Function2, java.io.Serializable { double apply$mcDDI$sp(double v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDDI$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcDDJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDDJ$sp.java index f96b19dff7ed..3d4f4a7cded9 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDDJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDDJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDDJ$sp extends JFunction2 { +public interface JFunction2$mcDDJ$sp extends scala.Function2, java.io.Serializable { double apply$mcDDJ$sp(double v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDDJ$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcDID$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDID$sp.java index 944f469a6dba..bd6652e51ac1 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDID$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDID$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDID$sp extends JFunction2 { +public interface JFunction2$mcDID$sp extends scala.Function2, java.io.Serializable { double apply$mcDID$sp(int v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDID$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcDII$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDII$sp.java index a04f616b5a7c..d06a246d3385 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDII$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDII$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDII$sp extends JFunction2 { +public interface JFunction2$mcDII$sp extends scala.Function2, java.io.Serializable { double apply$mcDII$sp(int v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDII$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcDIJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDIJ$sp.java index 3a7d33d4a50e..cda23c4dcd74 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDIJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDIJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDIJ$sp extends JFunction2 { +public interface JFunction2$mcDIJ$sp extends scala.Function2, java.io.Serializable { double apply$mcDIJ$sp(int v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDIJ$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcDJD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDJD$sp.java index 86b48486e648..723efd8451eb 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDJD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDJD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDJD$sp extends JFunction2 { +public interface JFunction2$mcDJD$sp extends scala.Function2, java.io.Serializable { double apply$mcDJD$sp(long v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDJD$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcDJI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDJI$sp.java index b9375c787025..c90352ef301b 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDJI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDJI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDJI$sp extends JFunction2 { +public interface JFunction2$mcDJI$sp extends scala.Function2, java.io.Serializable { double apply$mcDJI$sp(long v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDJI$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcDJJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcDJJ$sp.java index 4adbd17e148f..33612197878e 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcDJJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcDJJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcDJJ$sp extends JFunction2 { +public interface JFunction2$mcDJJ$sp extends scala.Function2, java.io.Serializable { double apply$mcDJJ$sp(long v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToDouble(apply$mcDJJ$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFDD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFDD$sp.java index 7e53d117c7f0..2b9236b5d1b4 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFDD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFDD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFDD$sp extends JFunction2 { +public interface JFunction2$mcFDD$sp extends scala.Function2, java.io.Serializable { float apply$mcFDD$sp(double v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFDD$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFDI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFDI$sp.java index 64c4b2f133e9..2c564962a716 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFDI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFDI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFDI$sp extends JFunction2 { +public interface JFunction2$mcFDI$sp extends scala.Function2, java.io.Serializable { float apply$mcFDI$sp(double v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFDI$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFDJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFDJ$sp.java index c7ffcbc66a9e..a0785f4cd2c6 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFDJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFDJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFDJ$sp extends JFunction2 { +public interface JFunction2$mcFDJ$sp extends scala.Function2, java.io.Serializable { float apply$mcFDJ$sp(double v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFDJ$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFID$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFID$sp.java index 43944751e68a..ba67ddb5931d 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFID$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFID$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFID$sp extends JFunction2 { +public interface JFunction2$mcFID$sp extends scala.Function2, java.io.Serializable { float apply$mcFID$sp(int v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFID$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFII$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFII$sp.java index a9a4540ca380..d58284b7522d 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFII$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFII$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFII$sp extends JFunction2 { +public interface JFunction2$mcFII$sp extends scala.Function2, java.io.Serializable { float apply$mcFII$sp(int v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFII$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFIJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFIJ$sp.java index 217615c7a3ab..4bc6eeb9085f 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFIJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFIJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFIJ$sp extends JFunction2 { +public interface JFunction2$mcFIJ$sp extends scala.Function2, java.io.Serializable { float apply$mcFIJ$sp(int v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFIJ$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFJD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFJD$sp.java index 8400e478769b..f2435e23f7fd 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFJD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFJD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFJD$sp extends JFunction2 { +public interface JFunction2$mcFJD$sp extends scala.Function2, java.io.Serializable { float apply$mcFJD$sp(long v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFJD$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFJI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFJI$sp.java index e6b6259f96b9..1362d00e9408 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFJI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFJI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFJI$sp extends JFunction2 { +public interface JFunction2$mcFJI$sp extends scala.Function2, java.io.Serializable { float apply$mcFJI$sp(long v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFJI$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcFJJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcFJJ$sp.java index 68a4c8ecc0ec..c9bcf515b736 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcFJJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcFJJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcFJJ$sp extends JFunction2 { +public interface JFunction2$mcFJJ$sp extends scala.Function2, java.io.Serializable { float apply$mcFJJ$sp(long v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToFloat(apply$mcFJJ$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIDD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIDD$sp.java index 76fe0b6ead42..28693910a57c 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIDD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIDD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIDD$sp extends JFunction2 { +public interface JFunction2$mcIDD$sp extends scala.Function2, java.io.Serializable { int apply$mcIDD$sp(double v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIDD$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIDI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIDI$sp.java index 908078f73528..50c775fbd9fc 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIDI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIDI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIDI$sp extends JFunction2 { +public interface JFunction2$mcIDI$sp extends scala.Function2, java.io.Serializable { int apply$mcIDI$sp(double v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIDI$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIDJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIDJ$sp.java index 35c943e32466..3231aa7a888b 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIDJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIDJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIDJ$sp extends JFunction2 { +public interface JFunction2$mcIDJ$sp extends scala.Function2, java.io.Serializable { int apply$mcIDJ$sp(double v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIDJ$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIID$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIID$sp.java index f245ec8788ae..01568b2fd626 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIID$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIID$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIID$sp extends JFunction2 { +public interface JFunction2$mcIID$sp extends scala.Function2, java.io.Serializable { int apply$mcIID$sp(int v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIID$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIII$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIII$sp.java index f3a7a56dffe3..e0fba76675cc 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIII$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIII$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIII$sp extends JFunction2 { +public interface JFunction2$mcIII$sp extends scala.Function2, java.io.Serializable { int apply$mcIII$sp(int v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIII$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIIJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIIJ$sp.java index 9736196b9ee6..7155548e9f01 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIIJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIIJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIIJ$sp extends JFunction2 { +public interface JFunction2$mcIIJ$sp extends scala.Function2, java.io.Serializable { int apply$mcIIJ$sp(int v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIIJ$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIJD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIJD$sp.java index 3211432ccb2a..f541cfdef405 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIJD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIJD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIJD$sp extends JFunction2 { +public interface JFunction2$mcIJD$sp extends scala.Function2, java.io.Serializable { int apply$mcIJD$sp(long v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIJD$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIJI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIJI$sp.java index 74f76404e060..e484efe42778 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIJI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIJI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIJI$sp extends JFunction2 { +public interface JFunction2$mcIJI$sp extends scala.Function2, java.io.Serializable { int apply$mcIJI$sp(long v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIJI$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcIJJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcIJJ$sp.java index 7b9060bcb830..ec3538779cb6 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcIJJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcIJJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcIJJ$sp extends JFunction2 { +public interface JFunction2$mcIJJ$sp extends scala.Function2, java.io.Serializable { int apply$mcIJJ$sp(long v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToInteger(apply$mcIJJ$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJDD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJDD$sp.java index b4595cdf6ae9..b13502de5b30 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJDD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJDD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJDD$sp extends JFunction2 { +public interface JFunction2$mcJDD$sp extends scala.Function2, java.io.Serializable { long apply$mcJDD$sp(double v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJDD$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJDI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJDI$sp.java index 59aad669e79a..9ec9adda6003 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJDI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJDI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJDI$sp extends JFunction2 { +public interface JFunction2$mcJDI$sp extends scala.Function2, java.io.Serializable { long apply$mcJDI$sp(double v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJDI$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJDJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJDJ$sp.java index 8111e0361715..68ef9ead143a 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJDJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJDJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJDJ$sp extends JFunction2 { +public interface JFunction2$mcJDJ$sp extends scala.Function2, java.io.Serializable { long apply$mcJDJ$sp(double v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJDJ$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJID$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJID$sp.java index 8a06a40a4ab2..29c9c5e3d300 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJID$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJID$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJID$sp extends JFunction2 { +public interface JFunction2$mcJID$sp extends scala.Function2, java.io.Serializable { long apply$mcJID$sp(int v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJID$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJII$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJII$sp.java index 3d2e03ddbc70..bb23086125bf 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJII$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJII$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJII$sp extends JFunction2 { +public interface JFunction2$mcJII$sp extends scala.Function2, java.io.Serializable { long apply$mcJII$sp(int v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJII$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJIJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJIJ$sp.java index 32408269c8b7..649fe2432562 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJIJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJIJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJIJ$sp extends JFunction2 { +public interface JFunction2$mcJIJ$sp extends scala.Function2, java.io.Serializable { long apply$mcJIJ$sp(int v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJIJ$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJJD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJJD$sp.java index cf75bc5c197f..8e6071d44817 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJJD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJJD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJJD$sp extends JFunction2 { +public interface JFunction2$mcJJD$sp extends scala.Function2, java.io.Serializable { long apply$mcJJD$sp(long v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJJD$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJJI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJJI$sp.java index eddcea671dc1..61366ac26de1 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJJI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJJI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJJI$sp extends JFunction2 { +public interface JFunction2$mcJJI$sp extends scala.Function2, java.io.Serializable { long apply$mcJJI$sp(long v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJJI$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcJJJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcJJJ$sp.java index 4f5626a3e695..a44e97318e11 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcJJJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcJJJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcJJJ$sp extends JFunction2 { +public interface JFunction2$mcJJJ$sp extends scala.Function2, java.io.Serializable { long apply$mcJJJ$sp(long v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToLong(apply$mcJJJ$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVDD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVDD$sp.java index 45b9739c91fc..8e7cbd7d1bd2 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVDD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVDD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVDD$sp extends JFunction2 { +public interface JFunction2$mcVDD$sp extends scala.Function2, java.io.Serializable { void apply$mcVDD$sp(double v1, double v2); default Object apply(Object v1, Object v2) { apply$mcVDD$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVDI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVDI$sp.java index c344ea501751..1dee353d6b32 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVDI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVDI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVDI$sp extends JFunction2 { +public interface JFunction2$mcVDI$sp extends scala.Function2, java.io.Serializable { void apply$mcVDI$sp(double v1, int v2); default Object apply(Object v1, Object v2) { apply$mcVDI$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToInt(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVDJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVDJ$sp.java index 94b01d59d58d..0b9560868472 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVDJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVDJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVDJ$sp extends JFunction2 { +public interface JFunction2$mcVDJ$sp extends scala.Function2, java.io.Serializable { void apply$mcVDJ$sp(double v1, long v2); default Object apply(Object v1, Object v2) { apply$mcVDJ$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToLong(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVID$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVID$sp.java index 47c29525a75f..f0ed7e7e9789 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVID$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVID$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVID$sp extends JFunction2 { +public interface JFunction2$mcVID$sp extends scala.Function2, java.io.Serializable { void apply$mcVID$sp(int v1, double v2); default Object apply(Object v1, Object v2) { apply$mcVID$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVII$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVII$sp.java index 546a994cb990..52d7922cc1aa 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVII$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVII$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVII$sp extends JFunction2 { +public interface JFunction2$mcVII$sp extends scala.Function2, java.io.Serializable { void apply$mcVII$sp(int v1, int v2); default Object apply(Object v1, Object v2) { apply$mcVII$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToInt(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVIJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVIJ$sp.java index d9871efee33a..ac256bf163d6 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVIJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVIJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVIJ$sp extends JFunction2 { +public interface JFunction2$mcVIJ$sp extends scala.Function2, java.io.Serializable { void apply$mcVIJ$sp(int v1, long v2); default Object apply(Object v1, Object v2) { apply$mcVIJ$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToLong(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVJD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVJD$sp.java index 525c8ee059fc..6e2dea3fbfef 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVJD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVJD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVJD$sp extends JFunction2 { +public interface JFunction2$mcVJD$sp extends scala.Function2, java.io.Serializable { void apply$mcVJD$sp(long v1, double v2); default Object apply(Object v1, Object v2) { apply$mcVJD$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVJI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVJI$sp.java index 98f33bf9420e..d1cba439e667 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVJI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVJI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVJI$sp extends JFunction2 { +public interface JFunction2$mcVJI$sp extends scala.Function2, java.io.Serializable { void apply$mcVJI$sp(long v1, int v2); default Object apply(Object v1, Object v2) { apply$mcVJI$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToInt(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcVJJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcVJJ$sp.java index adb8934b57eb..67f848a60e7c 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcVJJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcVJJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcVJJ$sp extends JFunction2 { +public interface JFunction2$mcVJJ$sp extends scala.Function2, java.io.Serializable { void apply$mcVJJ$sp(long v1, long v2); default Object apply(Object v1, Object v2) { apply$mcVJJ$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToLong(v2)); return scala.runtime.BoxedUnit.UNIT; } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZDD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZDD$sp.java index 9272e025a652..b430c5f1343f 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZDD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZDD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZDD$sp extends JFunction2 { +public interface JFunction2$mcZDD$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZDD$sp(double v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZDD$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZDI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZDI$sp.java index 4406e00abdc2..01fb8ba003e6 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZDI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZDI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZDI$sp extends JFunction2 { +public interface JFunction2$mcZDI$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZDI$sp(double v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZDI$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZDJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZDJ$sp.java index 1f92dddfafcb..a7d28e3cfc71 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZDJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZDJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZDJ$sp extends JFunction2 { +public interface JFunction2$mcZDJ$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZDJ$sp(double v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZDJ$sp(scala.runtime.BoxesRunTime.unboxToDouble(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZID$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZID$sp.java index 06b73f9897fc..e77719bf7568 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZID$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZID$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZID$sp extends JFunction2 { +public interface JFunction2$mcZID$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZID$sp(int v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZID$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZII$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZII$sp.java index 729f86063f9d..5f1f83aaf8b2 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZII$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZII$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZII$sp extends JFunction2 { +public interface JFunction2$mcZII$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZII$sp(int v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZII$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZIJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZIJ$sp.java index 38da681cd196..38fabd6f691c 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZIJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZIJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZIJ$sp extends JFunction2 { +public interface JFunction2$mcZIJ$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZIJ$sp(int v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZIJ$sp(scala.runtime.BoxesRunTime.unboxToInt(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZJD$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZJD$sp.java index 6dc9534811f5..59c82cb01e60 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZJD$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZJD$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZJD$sp extends JFunction2 { +public interface JFunction2$mcZJD$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZJD$sp(long v1, double v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZJD$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToDouble(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZJI$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZJI$sp.java index a86f63be366a..3e73b8a794e8 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZJI$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZJI$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZJI$sp extends JFunction2 { +public interface JFunction2$mcZJI$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZJI$sp(long v1, int v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZJI$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToInt(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2$mcZJJ$sp.java b/src/library/scala/runtime/java8/JFunction2$mcZJJ$sp.java index 728a781e8ecf..96a14e98a531 100644 --- a/src/library/scala/runtime/java8/JFunction2$mcZJJ$sp.java +++ b/src/library/scala/runtime/java8/JFunction2$mcZJJ$sp.java @@ -6,7 +6,7 @@ package scala.runtime.java8; @FunctionalInterface -public interface JFunction2$mcZJJ$sp extends JFunction2 { +public interface JFunction2$mcZJJ$sp extends scala.Function2, java.io.Serializable { boolean apply$mcZJJ$sp(long v1, long v2); default Object apply(Object v1, Object v2) { return scala.runtime.BoxesRunTime.boxToBoolean(apply$mcZJJ$sp(scala.runtime.BoxesRunTime.unboxToLong(v1), scala.runtime.BoxesRunTime.unboxToLong(v2))); } diff --git a/src/library/scala/runtime/java8/JFunction2.java b/src/library/scala/runtime/java8/JFunction2.java deleted file mode 100644 index 548ff60cf618..000000000000 --- a/src/library/scala/runtime/java8/JFunction2.java +++ /dev/null @@ -1,498 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction2 extends scala.Function2, java.io.Serializable { - default void apply$mcVII$sp(int v1, int v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2)); - } - default boolean apply$mcZII$sp(int v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default int apply$mcIII$sp(int v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default float apply$mcFII$sp(int v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default long apply$mcJII$sp(int v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default double apply$mcDII$sp(int v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default void apply$mcVIJ$sp(int v1, long v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2)); - } - default boolean apply$mcZIJ$sp(int v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default int apply$mcIIJ$sp(int v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default float apply$mcFIJ$sp(int v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default long apply$mcJIJ$sp(int v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default double apply$mcDIJ$sp(int v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default void apply$mcVID$sp(int v1, double v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2)); - } - default boolean apply$mcZID$sp(int v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default int apply$mcIID$sp(int v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default float apply$mcFID$sp(int v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default long apply$mcJID$sp(int v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default double apply$mcDID$sp(int v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToInteger(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default void apply$mcVJI$sp(long v1, int v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2)); - } - default boolean apply$mcZJI$sp(long v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default int apply$mcIJI$sp(long v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default float apply$mcFJI$sp(long v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default long apply$mcJJI$sp(long v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default double apply$mcDJI$sp(long v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default void apply$mcVJJ$sp(long v1, long v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2)); - } - default boolean apply$mcZJJ$sp(long v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default int apply$mcIJJ$sp(long v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default float apply$mcFJJ$sp(long v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default long apply$mcJJJ$sp(long v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default double apply$mcDJJ$sp(long v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default void apply$mcVJD$sp(long v1, double v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2)); - } - default boolean apply$mcZJD$sp(long v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default int apply$mcIJD$sp(long v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default float apply$mcFJD$sp(long v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default long apply$mcJJD$sp(long v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default double apply$mcDJD$sp(long v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToLong(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default void apply$mcVDI$sp(double v1, int v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2)); - } - default boolean apply$mcZDI$sp(double v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default int apply$mcIDI$sp(double v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default float apply$mcFDI$sp(double v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default long apply$mcJDI$sp(double v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default double apply$mcDDI$sp(double v1, int v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToInteger(v2))); - } - default void apply$mcVDJ$sp(double v1, long v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2)); - } - default boolean apply$mcZDJ$sp(double v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default int apply$mcIDJ$sp(double v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default float apply$mcFDJ$sp(double v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default long apply$mcJDJ$sp(double v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default double apply$mcDDJ$sp(double v1, long v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToLong(v2))); - } - default void apply$mcVDD$sp(double v1, double v2) { - apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2)); - } - default boolean apply$mcZDD$sp(double v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToBoolean(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default int apply$mcIDD$sp(double v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToInt(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default float apply$mcFDD$sp(double v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToFloat(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default long apply$mcJDD$sp(double v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToLong(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - default double apply$mcDDD$sp(double v1, double v2) { - return scala.runtime.BoxesRunTime.unboxToDouble(apply((T1) scala.runtime.BoxesRunTime.boxToDouble(v1), (T2) scala.runtime.BoxesRunTime.boxToDouble(v2))); - } - - default scala.Function1 curried$mcVII$sp() { - return curried(); - } - default scala.Function1 curried$mcZII$sp() { - return curried(); - } - default scala.Function1 curried$mcIII$sp() { - return curried(); - } - default scala.Function1 curried$mcFII$sp() { - return curried(); - } - default scala.Function1 curried$mcJII$sp() { - return curried(); - } - default scala.Function1 curried$mcDII$sp() { - return curried(); - } - default scala.Function1 curried$mcVIJ$sp() { - return curried(); - } - default scala.Function1 curried$mcZIJ$sp() { - return curried(); - } - default scala.Function1 curried$mcIIJ$sp() { - return curried(); - } - default scala.Function1 curried$mcFIJ$sp() { - return curried(); - } - default scala.Function1 curried$mcJIJ$sp() { - return curried(); - } - default scala.Function1 curried$mcDIJ$sp() { - return curried(); - } - default scala.Function1 curried$mcVID$sp() { - return curried(); - } - default scala.Function1 curried$mcZID$sp() { - return curried(); - } - default scala.Function1 curried$mcIID$sp() { - return curried(); - } - default scala.Function1 curried$mcFID$sp() { - return curried(); - } - default scala.Function1 curried$mcJID$sp() { - return curried(); - } - default scala.Function1 curried$mcDID$sp() { - return curried(); - } - default scala.Function1 curried$mcVJI$sp() { - return curried(); - } - default scala.Function1 curried$mcZJI$sp() { - return curried(); - } - default scala.Function1 curried$mcIJI$sp() { - return curried(); - } - default scala.Function1 curried$mcFJI$sp() { - return curried(); - } - default scala.Function1 curried$mcJJI$sp() { - return curried(); - } - default scala.Function1 curried$mcDJI$sp() { - return curried(); - } - default scala.Function1 curried$mcVJJ$sp() { - return curried(); - } - default scala.Function1 curried$mcZJJ$sp() { - return curried(); - } - default scala.Function1 curried$mcIJJ$sp() { - return curried(); - } - default scala.Function1 curried$mcFJJ$sp() { - return curried(); - } - default scala.Function1 curried$mcJJJ$sp() { - return curried(); - } - default scala.Function1 curried$mcDJJ$sp() { - return curried(); - } - default scala.Function1 curried$mcVJD$sp() { - return curried(); - } - default scala.Function1 curried$mcZJD$sp() { - return curried(); - } - default scala.Function1 curried$mcIJD$sp() { - return curried(); - } - default scala.Function1 curried$mcFJD$sp() { - return curried(); - } - default scala.Function1 curried$mcJJD$sp() { - return curried(); - } - default scala.Function1 curried$mcDJD$sp() { - return curried(); - } - default scala.Function1 curried$mcVDI$sp() { - return curried(); - } - default scala.Function1 curried$mcZDI$sp() { - return curried(); - } - default scala.Function1 curried$mcIDI$sp() { - return curried(); - } - default scala.Function1 curried$mcFDI$sp() { - return curried(); - } - default scala.Function1 curried$mcJDI$sp() { - return curried(); - } - default scala.Function1 curried$mcDDI$sp() { - return curried(); - } - default scala.Function1 curried$mcVDJ$sp() { - return curried(); - } - default scala.Function1 curried$mcZDJ$sp() { - return curried(); - } - default scala.Function1 curried$mcIDJ$sp() { - return curried(); - } - default scala.Function1 curried$mcFDJ$sp() { - return curried(); - } - default scala.Function1 curried$mcJDJ$sp() { - return curried(); - } - default scala.Function1 curried$mcDDJ$sp() { - return curried(); - } - default scala.Function1 curried$mcVDD$sp() { - return curried(); - } - default scala.Function1 curried$mcZDD$sp() { - return curried(); - } - default scala.Function1 curried$mcIDD$sp() { - return curried(); - } - default scala.Function1 curried$mcFDD$sp() { - return curried(); - } - default scala.Function1 curried$mcJDD$sp() { - return curried(); - } - default scala.Function1 curried$mcDDD$sp() { - return curried(); - } - - default scala.Function1 tupled$mcVII$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZII$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIII$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFII$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJII$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDII$sp() { - return tupled(); - } - default scala.Function1 tupled$mcVIJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZIJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIIJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFIJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJIJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDIJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcVID$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZID$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIID$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFID$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJID$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDID$sp() { - return tupled(); - } - default scala.Function1 tupled$mcVJI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZJI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIJI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFJI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJJI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDJI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcVJJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZJJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIJJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFJJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJJJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDJJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcVJD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZJD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIJD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFJD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJJD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDJD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcVDI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZDI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIDI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFDI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJDI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDDI$sp() { - return tupled(); - } - default scala.Function1 tupled$mcVDJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZDJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIDJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFDJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJDJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDDJ$sp() { - return tupled(); - } - default scala.Function1 tupled$mcVDD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcZDD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcIDD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcFDD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcJDD$sp() { - return tupled(); - } - default scala.Function1 tupled$mcDDD$sp() { - return tupled(); - } -} diff --git a/src/library/scala/runtime/java8/JFunction20.java b/src/library/scala/runtime/java8/JFunction20.java deleted file mode 100644 index 5505743c20e4..000000000000 --- a/src/library/scala/runtime/java8/JFunction20.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction20 extends scala.Function20, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction21.java b/src/library/scala/runtime/java8/JFunction21.java deleted file mode 100644 index 80e96d37150f..000000000000 --- a/src/library/scala/runtime/java8/JFunction21.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction21 extends scala.Function21, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction22.java b/src/library/scala/runtime/java8/JFunction22.java deleted file mode 100644 index 45e689458b5a..000000000000 --- a/src/library/scala/runtime/java8/JFunction22.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction22 extends scala.Function22, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction3.java b/src/library/scala/runtime/java8/JFunction3.java deleted file mode 100644 index 6d81bb3a189f..000000000000 --- a/src/library/scala/runtime/java8/JFunction3.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction3 extends scala.Function3, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction4.java b/src/library/scala/runtime/java8/JFunction4.java deleted file mode 100644 index 6c5cd3b61d3c..000000000000 --- a/src/library/scala/runtime/java8/JFunction4.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction4 extends scala.Function4, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction5.java b/src/library/scala/runtime/java8/JFunction5.java deleted file mode 100644 index eca1a406a63f..000000000000 --- a/src/library/scala/runtime/java8/JFunction5.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction5 extends scala.Function5, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction6.java b/src/library/scala/runtime/java8/JFunction6.java deleted file mode 100644 index 1c9daed5aa05..000000000000 --- a/src/library/scala/runtime/java8/JFunction6.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction6 extends scala.Function6, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction7.java b/src/library/scala/runtime/java8/JFunction7.java deleted file mode 100644 index c1aa130ba1d1..000000000000 --- a/src/library/scala/runtime/java8/JFunction7.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction7 extends scala.Function7, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction8.java b/src/library/scala/runtime/java8/JFunction8.java deleted file mode 100644 index 425e694df8cc..000000000000 --- a/src/library/scala/runtime/java8/JFunction8.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction8 extends scala.Function8, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JFunction9.java b/src/library/scala/runtime/java8/JFunction9.java deleted file mode 100644 index 21c3c8c6e30c..000000000000 --- a/src/library/scala/runtime/java8/JFunction9.java +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -@FunctionalInterface -public interface JFunction9 extends scala.Function9, java.io.Serializable { -} diff --git a/src/library/scala/runtime/java8/JProcedure0.java b/src/library/scala/runtime/java8/JProcedure0.java deleted file mode 100644 index 6004364d0326..000000000000 --- a/src/library/scala/runtime/java8/JProcedure0.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure0 extends JFunction0 { - default void $init$() { - } - - void applyVoid(); - - default BoxedUnit apply() { - applyVoid(); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure1.java b/src/library/scala/runtime/java8/JProcedure1.java deleted file mode 100644 index 184d943042d4..000000000000 --- a/src/library/scala/runtime/java8/JProcedure1.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure1 extends JFunction1 { - default void $init$() { - } - - void applyVoid(T1 t1); - - default BoxedUnit apply(T1 t1) { - applyVoid(t1); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure10.java b/src/library/scala/runtime/java8/JProcedure10.java deleted file mode 100644 index 2aadd7d21596..000000000000 --- a/src/library/scala/runtime/java8/JProcedure10.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure10 extends JFunction10 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure11.java b/src/library/scala/runtime/java8/JProcedure11.java deleted file mode 100644 index c29853be1f57..000000000000 --- a/src/library/scala/runtime/java8/JProcedure11.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure11 extends JFunction11 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure12.java b/src/library/scala/runtime/java8/JProcedure12.java deleted file mode 100644 index 0607600c3373..000000000000 --- a/src/library/scala/runtime/java8/JProcedure12.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure12 extends JFunction12 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure13.java b/src/library/scala/runtime/java8/JProcedure13.java deleted file mode 100644 index c390fed2a510..000000000000 --- a/src/library/scala/runtime/java8/JProcedure13.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure13 extends JFunction13 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure14.java b/src/library/scala/runtime/java8/JProcedure14.java deleted file mode 100644 index d67cff1b5ae7..000000000000 --- a/src/library/scala/runtime/java8/JProcedure14.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure14 extends JFunction14 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure15.java b/src/library/scala/runtime/java8/JProcedure15.java deleted file mode 100644 index 81e0f524f552..000000000000 --- a/src/library/scala/runtime/java8/JProcedure15.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure15 extends JFunction15 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure16.java b/src/library/scala/runtime/java8/JProcedure16.java deleted file mode 100644 index 3d29ae25c56e..000000000000 --- a/src/library/scala/runtime/java8/JProcedure16.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure16 extends JFunction16 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure17.java b/src/library/scala/runtime/java8/JProcedure17.java deleted file mode 100644 index 85f40b2cd56e..000000000000 --- a/src/library/scala/runtime/java8/JProcedure17.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure17 extends JFunction17 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure18.java b/src/library/scala/runtime/java8/JProcedure18.java deleted file mode 100644 index fe2ab6f22c16..000000000000 --- a/src/library/scala/runtime/java8/JProcedure18.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure18 extends JFunction18 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure19.java b/src/library/scala/runtime/java8/JProcedure19.java deleted file mode 100644 index 9289d639a581..000000000000 --- a/src/library/scala/runtime/java8/JProcedure19.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure19 extends JFunction19 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18, T19 t19); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18, T19 t19) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure2.java b/src/library/scala/runtime/java8/JProcedure2.java deleted file mode 100644 index 273357a3b0a4..000000000000 --- a/src/library/scala/runtime/java8/JProcedure2.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure2 extends JFunction2 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2); - - default BoxedUnit apply(T1 t1, T2 t2) { - applyVoid(t1, t2); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure20.java b/src/library/scala/runtime/java8/JProcedure20.java deleted file mode 100644 index 8701e9d4225b..000000000000 --- a/src/library/scala/runtime/java8/JProcedure20.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure20 extends JFunction20 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18, T19 t19, T20 t20); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18, T19 t19, T20 t20) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure21.java b/src/library/scala/runtime/java8/JProcedure21.java deleted file mode 100644 index f8e38f6c70d7..000000000000 --- a/src/library/scala/runtime/java8/JProcedure21.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure21 extends JFunction21 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18, T19 t19, T20 t20, T21 t21); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18, T19 t19, T20 t20, T21 t21) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure22.java b/src/library/scala/runtime/java8/JProcedure22.java deleted file mode 100644 index 8bae4d7e0d91..000000000000 --- a/src/library/scala/runtime/java8/JProcedure22.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure22 extends JFunction22 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18, T19 t19, T20 t20, T21 t21, T22 t22); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15, T16 t16, T17 t17, T18 t18, T19 t19, T20 t20, T21 t21, T22 t22) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure3.java b/src/library/scala/runtime/java8/JProcedure3.java deleted file mode 100644 index 7c53187f3118..000000000000 --- a/src/library/scala/runtime/java8/JProcedure3.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure3 extends JFunction3 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3) { - applyVoid(t1, t2, t3); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure4.java b/src/library/scala/runtime/java8/JProcedure4.java deleted file mode 100644 index 33161bc1517c..000000000000 --- a/src/library/scala/runtime/java8/JProcedure4.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure4 extends JFunction4 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4) { - applyVoid(t1, t2, t3, t4); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure5.java b/src/library/scala/runtime/java8/JProcedure5.java deleted file mode 100644 index c834c48bf693..000000000000 --- a/src/library/scala/runtime/java8/JProcedure5.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure5 extends JFunction5 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { - applyVoid(t1, t2, t3, t4, t5); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure6.java b/src/library/scala/runtime/java8/JProcedure6.java deleted file mode 100644 index 995bdd6734f1..000000000000 --- a/src/library/scala/runtime/java8/JProcedure6.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure6 extends JFunction6 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { - applyVoid(t1, t2, t3, t4, t5, t6); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure7.java b/src/library/scala/runtime/java8/JProcedure7.java deleted file mode 100644 index 1821d8d406ff..000000000000 --- a/src/library/scala/runtime/java8/JProcedure7.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure7 extends JFunction7 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { - applyVoid(t1, t2, t3, t4, t5, t6, t7); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure8.java b/src/library/scala/runtime/java8/JProcedure8.java deleted file mode 100644 index 4b9dd0929a3c..000000000000 --- a/src/library/scala/runtime/java8/JProcedure8.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure8 extends JFunction8 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8); - return BoxedUnit.UNIT; - } -} diff --git a/src/library/scala/runtime/java8/JProcedure9.java b/src/library/scala/runtime/java8/JProcedure9.java deleted file mode 100644 index c4cbc65b6c9d..000000000000 --- a/src/library/scala/runtime/java8/JProcedure9.java +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ - -package scala.runtime.java8; - -import scala.runtime.BoxedUnit; - -@FunctionalInterface -public interface JProcedure9 extends JFunction9 { - default void $init$() { - } - - void applyVoid(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9); - - default BoxedUnit apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) { - applyVoid(t1, t2, t3, t4, t5, t6, t7, t8, t9); - return BoxedUnit.UNIT; - } -} From 3205091c5530b41072dc0624a3362809bdadf6ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pociecha?= Date: Fri, 22 Jul 2016 12:11:55 +0200 Subject: [PATCH 149/153] Improve sbt-based IntelliJ integration in case of Windows Use File.pathSeparator when processing classpath instead of just : to don't end up with classpath like "C:\sth\a.jar:C:\sth\b.jar" what was causing problems after split(":"). Display questions first and then wait for user input. I tested on 3 computes and without flush the printed questions were always displayed just after user replied - never before. --- build.sbt | 6 +++++- project/plugins.sbt | 4 ++-- src/intellij/README.md | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/build.sbt b/build.sbt index 1d4e208da2e3..e53f15a3326c 100644 --- a/build.sbt +++ b/build.sbt @@ -936,7 +936,7 @@ intellij := { val modules: List[(String, Seq[File])] = { // for the sbt build module, the dependencies are fetched from the project's build using sbt-buildinfo - val buildModule = ("scala-build", scalabuild.BuildInfo.buildClasspath.split(":").toSeq.map(new File(_))) + val buildModule = ("scala-build", scalabuild.BuildInfo.buildClasspath.split(java.io.File.pathSeparator).toSeq.map(new File(_))) // `sbt projects` lists all modules in the build buildModule :: List( moduleDeps(compilerP).value, @@ -1015,12 +1015,14 @@ intellij := { var continue = false if (!ipr.exists) { scala.Console.print(s"Could not find src/intellij/scala.ipr. Create new project files from src/intellij/*.SAMPLE (y/N)? ") + scala.Console.flush() if (scala.Console.readLine() == "y") { intellijCreateFromSample((baseDirectory in ThisBuild).value) continue = true } } else { scala.Console.print("Update library classpaths in the current src/intellij/scala.ipr (y/N)? ") + scala.Console.flush() continue = scala.Console.readLine() == "y" } if (continue) { @@ -1045,6 +1047,7 @@ lazy val intellijFromSample = taskKey[Unit]("Create fresh IntelliJ project files intellijFromSample := { val s = streams.value scala.Console.print(s"Create new project files from src/intellij/*.SAMPLE (y/N)? ") + scala.Console.flush() if (scala.Console.readLine() == "y") intellijCreateFromSample((baseDirectory in ThisBuild).value) else @@ -1062,6 +1065,7 @@ lazy val intellijToSample = taskKey[Unit]("Update src/intellij/*.SAMPLE using th intellijToSample := { val s = streams.value scala.Console.print(s"Update src/intellij/*.SAMPLE using the current IntelliJ project files (y/N)? ") + scala.Console.flush() if (scala.Console.readLine() == "y") { val basedir = (baseDirectory in ThisBuild).value val existing = basedir / "src/intellij" * "*.SAMPLE" diff --git a/project/plugins.sbt b/project/plugins.sbt index 98ec8f16ed7a..0a5b8f3dd428 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -11,9 +11,9 @@ enablePlugins(BuildInfoPlugin) // configure sbt-buildinfo to send the externalDependencyClasspath to the main build, which allows using it for the IntelliJ project config -lazy val buildClasspath = taskKey[String]("Colon-separated list of entries on the sbt build classpath.") +lazy val buildClasspath = taskKey[String]("Colon-separated (or semicolon-separated in case of Windows) list of entries on the sbt build classpath.") -buildClasspath := (externalDependencyClasspath in Compile).value.map(_.data).mkString(":") +buildClasspath := (externalDependencyClasspath in Compile).value.map(_.data).mkString(java.io.File.pathSeparator) buildInfoKeys := Seq[BuildInfoKey](buildClasspath) diff --git a/src/intellij/README.md b/src/intellij/README.md index 650d91e5d104..7bd990288b3d 100644 --- a/src/intellij/README.md +++ b/src/intellij/README.md @@ -17,7 +17,7 @@ are ignored. ## Dependencies -For every module in the IntelliJ project there is a corresponding `-deps` library, for exmaple `compiler-deps` provides `ant.jar` for the compiler codebase. +For every module in the IntelliJ project there is a corresponding `-deps` library, for example `compiler-deps` provides `ant.jar` for the compiler codebase. The `.jar` files in these `-deps` libraries can be easily kept up-to-date by running `sbt intellij` again. This is necessary whenever the dependencies in the sbt build change, for example when the `starr` version is updated. From ce262e45141db642c2d5c7e4c7427f84fd08f854 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Fri, 22 Jul 2016 17:38:46 +0100 Subject: [PATCH 150/153] Added tests for SI-482/SI-4914 --- test/files/pos/t482.scala | 7 +++++++ test/files/pos/t4914.scala | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 test/files/pos/t482.scala create mode 100644 test/files/pos/t4914.scala diff --git a/test/files/pos/t482.scala b/test/files/pos/t482.scala new file mode 100644 index 000000000000..b121c933377a --- /dev/null +++ b/test/files/pos/t482.scala @@ -0,0 +1,7 @@ +object Test { + class Foo { val z = "foo"; val y : z.type = z } + + val x : ({ val y : z.type } forSome { val z : String }) = new Foo + + val x2 : ({ val y : T } forSome { type T <: String with Singleton }) = new Foo +} diff --git a/test/files/pos/t4914.scala b/test/files/pos/t4914.scala new file mode 100644 index 000000000000..a6c8ef5a4e22 --- /dev/null +++ b/test/files/pos/t4914.scala @@ -0,0 +1,20 @@ +trait Type { + type S +} + +class ConcreteType extends Type { + type S = Double +} + +trait Base { + type T <: Type + val m: Map[t#S, t#S] forSome { type t <: T with Singleton } + val n: Map[x.type#S, x.type#S] forSome { val x: T } +} + +abstract class Derived extends Base { + override type T = ConcreteType + override val m = Map[Double, Double]() + /** This does not work. §3.2.10 indicates that types n is shorthand for type of m. */ + override val n = Map[Double, Double]() +} From a2cba53e18864a5b9092f1e329c6e0afb09566c5 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 25 Jul 2016 10:21:26 +1000 Subject: [PATCH 151/153] SD-167 Fine tuning constructor pattern translation - Avoid calling NoSymbol.owner when checking whether we're dealing with a case class constructor pattern or a general extractor. Tested manually with the test case in the ticket, no more output is produced under `-Xdev`. - Be more conservative about the conversion to a case class pattern: rather than looking just at the type of the pattern tree, also look at the tree itself to ensure its safe to elide. This change is analagous to SI-4859, which restricted rewrites of case apply calls to case constructors. I've manually tested that case class patterns are still efficiently translated: ``` object Test { def main(args: Array[String]) { Some(1) match { case Some(x) => } } } ``` ``` % qscalac -Xprint:patmat sandbox/test.scala [[syntax trees at end of patmat]] // test.scala package { object Test extends scala.AnyRef { def (): Test.type = { Test.super.(); () }; def main(args: Array[String]): Unit = { case val x1: Some[Int] = scala.Some.apply[Int](1); case4(){ if (x1.ne(null)) matchEnd3(()) else case5() }; case5(){ matchEnd3(throw new MatchError(x1)) }; matchEnd3(x: Unit){ x } } } } ``` --- src/compiler/scala/tools/nsc/typechecker/Namers.scala | 2 +- .../scala/tools/nsc/typechecker/PatternTypers.scala | 3 ++- test/files/run/sd167.check | 1 + test/files/run/sd167.scala | 8 ++++++++ 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 test/files/run/sd167.check create mode 100644 test/files/run/sd167.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index ad9377f8b4bd..caad4a907b00 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1764,7 +1764,7 @@ trait Namers extends MethodSynthesis { * bugs waiting to be reported? If not, why not? When exactly do we need to * call this method? */ - def companionSymbolOf(original: Symbol, ctx: Context): Symbol = { + def companionSymbolOf(original: Symbol, ctx: Context): Symbol = if (original == NoSymbol) NoSymbol else { val owner = original.owner // SI-7264 Force the info of owners from previous compilation runs. // Doing this generally would trigger cycles; that's what we also diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala index f90e61ff9248..1df3449ce66e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala @@ -79,6 +79,7 @@ trait PatternTypers { // do not update the symbol if the tree's symbol's type does not define an unapply member // (e.g. since it's some method that returns an object with an unapply member) val fun = inPlaceAdHocOverloadingResolution(fun0)(hasUnapplyMember) + val canElide = treeInfo.isQualifierSafeToElide(fun) val caseClass = companionSymbolOf(fun.tpe.typeSymbol.sourceModule, context) val member = unapplyMember(fun.tpe) def resultType = (fun.tpe memberType member).finalResultType @@ -94,7 +95,7 @@ trait PatternTypers { // Dueling test cases: pos/overloaded-unapply.scala, run/case-class-23.scala, pos/t5022.scala // A case class with 23+ params has no unapply method. // A case class constructor may be overloaded with unapply methods in the companion. - if (caseClass.isCase && !member.isOverloaded) + if (canElide && caseClass.isCase && !member.isOverloaded) logResult(s"convertToCaseConstructor($fun, $caseClass, pt=$pt)")(convertToCaseConstructor(fun, caseClass, pt)) else if (!reallyExists(member)) CaseClassConstructorError(fun, s"${fun.symbol} is not a case class, nor does it have an unapply/unapplySeq member") diff --git a/test/files/run/sd167.check b/test/files/run/sd167.check new file mode 100644 index 000000000000..587be6b4c3f9 --- /dev/null +++ b/test/files/run/sd167.check @@ -0,0 +1 @@ +x diff --git a/test/files/run/sd167.scala b/test/files/run/sd167.scala new file mode 100644 index 000000000000..5095e772ad78 --- /dev/null +++ b/test/files/run/sd167.scala @@ -0,0 +1,8 @@ +object Test { + implicit class ToExtractor(val s: StringContext) { + def x = {println("x"); Some } + } + def main(args: Array[String]) { + Some(1) match { case x"${a}" => } // used to convert to `case Some(a) =>` and omit side effects + } +} From a84c7b9e8894f54d05e5f5f5f6e470f8db784090 Mon Sep 17 00:00:00 2001 From: Dima Tkach Date: Wed, 27 Jul 2016 10:14:48 -0400 Subject: [PATCH 152/153] Fixed some style issues --- src/library/scala/collection/mutable/ArrayOps.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index b384decbfb11..3329e350424d 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -44,9 +44,9 @@ sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomPara override def slice(from: Int, until: Int): Array[T] = { val lo = math.max(from, 0) val hi = math.min(math.max(until, 0), repr.length) - val size = math.max(hi-lo, 0) + val size = math.max(hi - lo, 0) val result = java.lang.reflect.Array.newInstance(elementClass, size) - if(size > 0) { + if (size > 0) { Array.copy(repr, lo, result, 0, size) } result.asInstanceOf[Array[T]] From c5fe4ba0e5eb0dd9d4a68163735211fe099eef79 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 28 Jul 2016 16:45:10 -0700 Subject: [PATCH 153/153] Prototype indy+unreflectSpecial for super calls --- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 16 ++++++------ .../tools/nsc/backend/jvm/BCodeHelpers.scala | 8 ------ .../nsc/backend/jvm/BCodeSkelBuilder.scala | 15 ++--------- .../scala/tools/nsc/backend/jvm/BTypes.scala | 6 +++-- .../nsc/backend/jvm/BTypesFromSymbols.scala | 18 +------------ .../tools/nsc/backend/jvm/CoreBTypes.scala | 19 ++++++++++++++ .../tools/nsc/backend/jvm/opt/LocalOpt.scala | 10 +++++--- .../tools/nsc/transform/Delambdafy.scala | 1 - .../scala/tools/nsc/transform/Mixin.scala | 19 -------------- src/library/scala/runtime/InvokeExact.java | 25 +++++++++++++++++++ test/files/run/sd143.scala | 19 ++++++++++++++ 11 files changed, 83 insertions(+), 73 deletions(-) create mode 100644 src/library/scala/runtime/InvokeExact.java create mode 100644 test/files/run/sd143.scala diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index d5c4b5e20161..d4b536f841df 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -1074,16 +1074,14 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { import InvokeStyle._ if (style == Super) { assert(receiverClass == methodOwner, s"for super call, expecting $receiverClass == $methodOwner") - if (receiverClass.isTrait && !receiverClass.isJavaDefined) { - val staticDesc = MethodBType(typeToBType(method.owner.info) :: bmType.argumentTypes, bmType.returnType).descriptor - val staticName = traitImplMethodName(method).toString - bc.invokestatic(receiverName, staticName, staticDesc, isInterface, pos) - } else { - if (receiverClass.isTraitOrInterface) { - // An earlier check in Mixin reports an error in this case, so it doesn't reach the backend - assert(cnode.interfaces.contains(receiverName), s"cannot invokespecial $receiverName.$jname, the interface is not a direct parent.") - } + if (method.isClassConstructor) { bc.invokespecial(receiverName, jname, mdescr, isInterface, pos) + } else if (method.isMixinConstructor) { + val staticName = method.javaSimpleName.toString + bc.invokestatic(receiverName, staticName, mdescr, isInterface, pos) + } else { + def staticDesc = MethodBType(typeToBType(method.owner.info) :: bmType.argumentTypes, bmType.returnType).descriptor + bc.jmethod.visitInvokeDynamicInsn(jname, staticDesc, coreBTypes.invokeExactBootstrapHandle, classBTypeFromSymbol(methodOwner).toASMType) } } else { val opc = style match { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index d779490ba84e..7167db95b6ad 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -50,14 +50,6 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { } } - def needsStaticImplMethod(sym: Symbol) = sym.hasAttachment[global.mixer.NeedStaticImpl.type] - - final def traitImplMethodName(sym: Symbol): Name = { - val name = sym.javaSimpleName - if (sym.isMixinConstructor) name - else name.append(nme.NAME_JOIN_STRING) - } - /** * True if `classSym` is an anonymous class or a local class. I.e., false if `classSym` is a * member class. This method is used to decide if we should emit an EnclosingMethod attribute. diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala index 1bff8519eca3..de5e75855bc2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala @@ -490,19 +490,8 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { case dd : DefDef => val sym = dd.symbol - if (needsStaticImplMethod(sym)) { - val staticDefDef = global.gen.mkStatic(dd, traitImplMethodName(sym), _.cloneSymbol) - val forwarderDefDef = { - val forwarderBody = Apply(global.gen.mkAttributedRef(staticDefDef.symbol), This(sym.owner).setType(sym.owner.typeConstructor) :: dd.vparamss.head.map(p => global.gen.mkAttributedIdent(p.symbol))).setType(sym.info.resultType) - // we don't want to the optimizer to inline the static method into the forwarder. Instead, - // the backend has a special case to transitively inline into a callsite of the forwarder - // when the forwarder itself is inlined. - forwarderBody.updateAttachment(NoInlineCallsiteAttachment) - deriveDefDef(dd)(_ => global.atPos(dd.pos)(forwarderBody)) - } - genDefDef(staticDefDef) - if (!sym.isMixinConstructor) - genDefDef(forwarderDefDef) + if (sym.isMixinConstructor) { + genDefDef(global.gen.mkStatic(dd, sym.javaSimpleName, sym => sym)) } else genDefDef(dd) case Template(_, _, body) => body foreach gen diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index 7b2686e7a9be..ae713ee7c514 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -11,7 +11,7 @@ import scala.collection.{concurrent, mutable} import scala.collection.concurrent.TrieMap import scala.reflect.internal.util.Position import scala.tools.asm -import asm.Opcodes +import asm.{Opcodes, Type} import scala.tools.asm.tree._ import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, MethodInlineInfo} import scala.tools.nsc.backend.jvm.BackendReporting._ @@ -1093,7 +1093,9 @@ abstract class BTypes { } } - final case class MethodBType(argumentTypes: List[BType], returnType: BType) extends BType + final case class MethodBType(argumentTypes: List[BType], returnType: BType) extends BType { + def toAsmType: Type = asm.Type.getMethodType(returnType.toASMType, argumentTypes.map(_.toASMType): _*) + } /* Some definitions that are required for the implementation of BTypes. They are abstract because * initializing them requires information from types / symbols, which is not accessible here in diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 383347a0d321..a7599f7c573b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -584,23 +584,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { annotatedInline = methodSym.hasAnnotation(ScalaInlineClass), annotatedNoInline = methodSym.hasAnnotation(ScalaNoInlineClass)) - if (needsStaticImplMethod(methodSym)) { - val staticName = traitImplMethodName(methodSym).toString - val selfParam = methodSym.newSyntheticValueParam(methodSym.owner.typeConstructor, nme.SELF) - val staticMethodType = methodSym.info match { - case mt @ MethodType(params, res) => copyMethodType(mt, selfParam :: params, res) - } - val staticMethodSignature = staticName + methodBTypeFromMethodType(staticMethodType, isConstructor = false) - val staticMethodInfo = MethodInlineInfo( - effectivelyFinal = true, - annotatedInline = info.annotatedInline, - annotatedNoInline = info.annotatedNoInline) - if (methodSym.isMixinConstructor) - List((staticMethodSignature, staticMethodInfo)) - else - List((signature, info), (staticMethodSignature, staticMethodInfo)) - } else - List((signature, info)) + List((signature, info)) } }).toMap diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index c2010d282828..c2b61733d740 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -103,6 +103,7 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { lazy val jlCloneableRef : ClassBType = classBTypeFromSymbol(JavaCloneableClass) // java/lang/Cloneable lazy val jiSerializableRef : ClassBType = classBTypeFromSymbol(JavaSerializableClass) // java/io/Serializable lazy val jlClassCastExceptionRef : ClassBType = classBTypeFromSymbol(ClassCastExceptionClass) // java/lang/ClassCastException + lazy val jlClassRef : ClassBType = classBTypeFromSymbol(ClassClass) // java/lang/Class lazy val juMapRef : ClassBType = classBTypeFromSymbol(JavaUtilMap) // java/util/Map lazy val juHashMapRef : ClassBType = classBTypeFromSymbol(JavaUtilHashMap) // java/util/HashMap lazy val sbScalaBeanInfoRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.beans.ScalaBeanInfo]) @@ -117,6 +118,7 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { lazy val srSymbolLiteral : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.SymbolLiteral]) lazy val srStructuralCallSite : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.StructuralCallSite]) lazy val srLambdaDeserialize : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.LambdaDeserialize]) + lazy val srInvokeExact : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.InvokeExact]) lazy val srBoxedUnitRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.BoxedUnit]) private def methodNameAndType(cls: Symbol, name: Name, static: Boolean = false, filterOverload: Symbol => Boolean = _ => true): MethodNameAndType = { @@ -288,6 +290,20 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { coreBTypes.jliCallSiteRef ).descriptor, /* itf = */ coreBTypes.srLambdaDeserialize.isInterface.get) + + lazy val invokeExactBootstrapHandle = + new scala.tools.asm.Handle(scala.tools.asm.Opcodes.H_INVOKESTATIC, + coreBTypes.srInvokeExact.internalName, sn.Bootstrap.toString, + MethodBType( + List( + coreBTypes.jliMethodHandlesLookupRef, + coreBTypes.StringRef, + coreBTypes.jliMethodTypeRef, + coreBTypes.jlClassRef + ), + coreBTypes.jliCallSiteRef + ).descriptor, + /* itf = */ coreBTypes.srInvokeExact.isInterface.get) } /** @@ -377,6 +393,7 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def jlThrowableRef : ClassBType = _coreBTypes.jlThrowableRef def jlCloneableRef : ClassBType = _coreBTypes.jlCloneableRef def jiSerializableRef : ClassBType = _coreBTypes.jiSerializableRef + def jlClassRef : ClassBType = _coreBTypes.jlClassRef def jlClassCastExceptionRef : ClassBType = _coreBTypes.jlClassCastExceptionRef def juMapRef : ClassBType = _coreBTypes.juMapRef def juHashMapRef : ClassBType = _coreBTypes.juHashMapRef @@ -410,6 +427,7 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def srSymbolLiteral : ClassBType = _coreBTypes.srSymbolLiteral def srStructuralCallSite : ClassBType = _coreBTypes.srStructuralCallSite def srLambdaDeserialize : ClassBType = _coreBTypes.srLambdaDeserialize + def srInvokeExact : ClassBType = _coreBTypes.srInvokeExact def typeOfArrayOp: Map[Int, BType] = _coreBTypes.typeOfArrayOp @@ -427,4 +445,5 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def lambdaMetaFactoryMetafactoryHandle : asm.Handle = _coreBTypes.lambdaMetaFactoryMetafactoryHandle def lambdaMetaFactoryAltMetafactoryHandle : asm.Handle = _coreBTypes.lambdaMetaFactoryAltMetafactoryHandle def lambdaDeserializeBootstrapHandle : asm.Handle = _coreBTypes.lambdaDeserializeBootstrapHandle + def invokeExactBootstrapHandle : asm.Handle = _coreBTypes.invokeExactBootstrapHandle } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala index 447ee209b593..a88f58126fd2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala @@ -7,10 +7,9 @@ package scala.tools.nsc package backend.jvm package opt -import scala.annotation.{tailrec, switch} - +import scala.annotation.{switch, tailrec} import scala.tools.asm.Type -import scala.tools.asm.tree.analysis.Frame +import scala.tools.asm.tree.analysis.{AnalyzerException, Frame} import scala.tools.asm.Opcodes._ import scala.tools.asm.tree._ import scala.collection.mutable @@ -201,7 +200,7 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { * * Returns `true` if the bytecode of `method` was changed. */ - def methodOptimizations(method: MethodNode, ownerClassName: InternalName): Boolean = { + def methodOptimizations(method: MethodNode, ownerClassName: InternalName): Boolean = try { if (method.instructions.size == 0) return false // fast path for abstract methods // unreachable-code also removes unused local variable nodes and empty exception handlers. @@ -383,6 +382,9 @@ class LocalOpt[BT <: BTypes](val btypes: BT) { assert(nullOrEmpty(method.invisibleLocalVariableAnnotations), method.invisibleLocalVariableAnnotations) nullnessDceBoxesCastsCopypropPushpopOrJumpsChanged || localsRemoved || lineNumbersRemoved || labelsRemoved + } catch { + case ex: AnalyzerException => + throw new AnalyzerException(ex.node, s"${ex.getMessage} + While optimizing: ${AsmUtils.textify(method)}", ex.getCause) } /** diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 855e53710bed..5ae32a6d564e 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -284,7 +284,6 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre // delambdafy targets are excluded as they are made static by `transformFunction`. if (!dd.symbol.hasFlag(STATIC) && !methodReferencesThis(dd.symbol)) { dd.symbol.setFlag(STATIC) - dd.symbol.removeAttachment[mixer.NeedStaticImpl.type] } super.transform(tree) case Apply(fun, outer :: rest) if shouldElideOuterArg(fun.symbol, outer) => diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index d62b77dac26e..1470fee75f41 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -130,10 +130,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ def addMember(clazz: Symbol, member: Symbol): Symbol = { debuglog(s"mixing into $clazz: ${member.defString}") - // This attachment is used to instruct the backend about which methids in traits require - // a static trait impl method. We remove this from the new symbol created for the method - // mixed into the subclass. - member.removeAttachment[NeedStaticImpl.type] clazz.info.decls enter member setFlag MIXEDIN resetFlag JAVA_DEFAULTMETHOD } def cloneAndAddMember(mixinClass: Symbol, mixinMember: Symbol, clazz: Symbol): Symbol = @@ -1017,11 +1013,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { } // add all new definitions to current class or interface val body1 = addNewDefs(currentOwner, bodyEmptyAccessors) - body1 foreach { - case dd: DefDef if isTraitMethodRequiringStaticImpl(dd) => - dd.symbol.updateAttachment(NeedStaticImpl) - case _ => - } treeCopy.Template(tree, parents1, self, body1) case Select(qual, name) if sym.owner.isTrait && !sym.isMethod => @@ -1056,14 +1047,4 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { finally localTyper = saved } } - - private def isTraitMethodRequiringStaticImpl(dd: DefDef): Boolean = { - val sym = dd.symbol - dd.rhs.nonEmpty && - sym.owner.isTrait && - !sym.isPrivate && // no need to put implementations of private methods into a static method - !sym.hasFlag(Flags.STATIC) - } - - case object NeedStaticImpl extends PlainAttachment } diff --git a/src/library/scala/runtime/InvokeExact.java b/src/library/scala/runtime/InvokeExact.java new file mode 100644 index 000000000000..e90a753cd940 --- /dev/null +++ b/src/library/scala/runtime/InvokeExact.java @@ -0,0 +1,25 @@ +package scala.runtime; + +import java.lang.invoke.*; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class InvokeExact { + private static MethodHandles.Lookup TRUSTED = getTrustedLookup(); + + public static CallSite bootstrap(MethodHandles.Lookup lookup, String invokedName, MethodType invokedType, + Class fromSite) throws Throwable { + Method method = fromSite.getMethod(invokedName, invokedType.dropParameterTypes(0, 1).parameterArray()); + return new ConstantCallSite(TRUSTED.unreflectSpecial(method, fromSite)); + } + + private static MethodHandles.Lookup getTrustedLookup() { + try { + Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); + field.setAccessible(true); + return (MethodHandles.Lookup) field.get(null); + } catch (ReflectiveOperationException e) { + return null; + } + } +} diff --git a/test/files/run/sd143.scala b/test/files/run/sd143.scala new file mode 100644 index 000000000000..5e003954c7f1 --- /dev/null +++ b/test/files/run/sd143.scala @@ -0,0 +1,19 @@ +class A { + def m = 1 +} + +class B extends A { + override def m = 2 +} + +trait T extends A + +class C extends B with T { + override def m = super[T].m +} + +object Test { + def main(args: Array[String]): Unit = { + println((new C).m) + } +}