From cb5daf3a5d9ab8195746e21801c3300d78efb52c Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 20 Feb 2016 22:51:12 -0800 Subject: [PATCH 01/58] 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 02/58] 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 03/58] 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 04/58] 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 5faad77ccebb41e9674b103d499de927c0dba662 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Fri, 6 May 2016 12:39:13 +0100 Subject: [PATCH 05/58] 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 06/58] 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 45e607d3879623d5163f47c17c717904f6867ef6 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Sat, 14 May 2016 14:12:43 +0100 Subject: [PATCH 07/58] 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 08/58] 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 883fdd74d63a54495f4013eef81c9b5ebc850d1c Mon Sep 17 00:00:00 2001 From: peterz Date: Tue, 10 May 2016 11:54:21 +0300 Subject: [PATCH 09/58] 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 214ea82573624bffb4d0f16f3e5c49f9370ba7a7 Mon Sep 17 00:00:00 2001 From: Steve Robinson Date: Sat, 27 Feb 2016 09:13:45 -0800 Subject: [PATCH 10/58] 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 11/58] 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 12/58] 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 13/58] 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 14/58] 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 15/58] 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 16/58] 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 17/58] 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 18/58] 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 19/58] 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 20/58] 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 21/58] 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 22/58] 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 23/58] 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 24/58] 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 25/58] 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 26/58] 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 093c9346dec958c46d0ae2e0473eaca463a5f922 Mon Sep 17 00:00:00 2001 From: chrisokasaki Date: Sun, 22 May 2016 21:54:06 -0400 Subject: [PATCH 27/58] 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 03d2de20047ad853d80c5c1aae68298082af27d3 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 25 Apr 2016 13:51:02 +0200 Subject: [PATCH 28/58] 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 90ca3fd6aeddd2aa54537cc940f4b69f2592b447 Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Mon, 23 May 2016 18:58:07 +0100 Subject: [PATCH 29/58] 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 892a6d6878accb67e3fe68aefaa256396db05a90 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Fri, 20 May 2016 12:49:25 +0100 Subject: [PATCH 30/58] 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 31/58] -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 60f28f9e6a330e91a0f1204917301d401a6fce72 Mon Sep 17 00:00:00 2001 From: Performant Data LLC Date: Mon, 25 Apr 2016 16:33:04 -0700 Subject: [PATCH 32/58] 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 33/58] 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 34/58] 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 35/58] 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 36/58] 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 37/58] 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 38/58] 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 39/58] 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 fd6386a51e9a5b97a83198a310923cd012e1aab0 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 26 May 2016 21:53:19 -0700 Subject: [PATCH 40/58] 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 981e3c51d5040ea808b5f699718db55241ee42cf Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Sat, 2 Apr 2016 12:40:25 +0200 Subject: [PATCH 41/58] 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 42/58] 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 43/58] 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 44/58] 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 45/58] 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 46/58] 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 47/58] 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 0533a3df71e9c855ac68e10d060c2c87d16994e0 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 4 May 2016 21:16:41 +1000 Subject: [PATCH 48/58] 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 49/58] 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 7a589e0335e6efb61afee539efb5d863365e5dff Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 19 May 2016 16:27:53 +1000 Subject: [PATCH 50/58] 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 b33e4a08a62132b5dff9a6258bf16d3693288a04 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 9 May 2016 10:34:35 +1000 Subject: [PATCH 51/58] 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 6d3c3f3863c2..c715a54f03c7 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 f882d16e9c9bf73d3e9b02e02b7135983ddfd2fa Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 31 May 2016 13:17:43 +1000 Subject: [PATCH 52/58] 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 c61795acaad5d466ecd20d10957d105f22f50912 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 31 May 2016 13:15:50 +1000 Subject: [PATCH 53/58] 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 4499c329ad9f3d734a205fd75fb30291daad2360 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 17 May 2016 14:36:40 +1000 Subject: [PATCH 54/58] 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 0cb67d1b1774d2d9cb347401f4fd149cf1e2866b Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 25 May 2016 15:21:50 +0200 Subject: [PATCH 55/58] 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/Symbols.scala | 2 +- .../tools/nsc/backend/jvm/DirectCompileTest.scala | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 3b886d357fde..62a33ad9a59b 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 e82e457504f730f5aaeb9e7e917467b36311369b Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 25 May 2016 15:22:19 +0200 Subject: [PATCH 56/58] 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 8943ec810d7e..0564232422af 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 6161dc7b7324..90360309ff0d 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 INVOKESPECIAL 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 INVOKESPECIAL 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 INVOKESPECIAL 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 INVOKESPECIAL 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 7234659a1d52..fdc17ec73f80 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 e7917908cbd370230279bfe5622fcdcbb1931ab6 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 4 May 2016 11:08:27 +1000 Subject: [PATCH 57/58] 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. ``` > ;scalac sandbox/test.scala ; scala Test [info] Running scala.tools.nsc.MainGenericRunner -usejavacp Test T C [success] Total time: 2 s, completed 04/05/2016 11:07:13 AM > eval "javap -classpath . -c -private C".!! [info] ans: String = Compiled from "test.scala" [info] public class C implements T { [info] public C(); [info] Code: [info] 0: aload_0 [info] 1: invokespecial #14 // Method java/lang/Object."":()V [info] 4: aload_0 [info] 5: invokespecial #17 // Method T.$init$:()V [info] 8: getstatic #23 // Field scala/Predef$.MODULE$:Lscala/Predef$; [info] 11: ldc #24 // String C [info] 13: invokevirtual #28 // Method scala/Predef$.println:(Ljava/lang/Object;)V [info] 16: aload_0 [info] 17: invokespecial #32 // Method T.foo:()I [info] 20: pop [info] 21: return [info] } > ;scalac -Yuse-trait-statics sandbox/test.scala ; scala Test [info] Running scala.tools.nsc.MainGenericRunner -usejavacp Test T C [success] Total time: 2 s, completed 04/05/2016 11:07:39 AM > eval "javap -classpath . -c -private C".!! [info] ans: String = Compiled from "test.scala" [info] public class C implements T { [info] public C(); [info] Code: [info] 0: aload_0 [info] 1: invokespecial #14 // Method java/lang/Object."":()V [info] 4: aload_0 [info] 5: invokestatic #18 // Method T.$init$:(LT;)V [info] 8: getstatic #24 // Field scala/Predef$.MODULE$:Lscala/Predef$; [info] 11: ldc #25 // String C [info] 13: invokevirtual #29 // Method scala/Predef$.println:(Ljava/lang/Object;)V [info] 16: aload_0 [info] 17: invokestatic #33 // Method T.foo:(LT;)I [info] 20: pop [info] 21: return [info] } > eval "javap -classpath . -c -private T".!! [info] ans: String = Compiled from "test.scala" [info] public interface T { [info] public static int foo(T); [info] Code: [info] 0: iconst_0 [info] 1: ireturn [info] [info] public int foo(); [info] Code: [info] 0: aload_0 [info] 1: invokestatic #15 // Method foo:(LT;)I [info] 4: ireturn [info] [info] public static void $init$(T); [info] Code: [info] 0: getstatic #24 // Field scala/Predef$.MODULE$:Lscala/Predef$; [info] 3: ldc #25 // String T [info] 5: invokevirtual #29 // Method scala/Predef$.println:(Ljava/lang/Object;)V [info] 8: return [info] [info] } ``` --- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 12 ++-- .../tools/nsc/backend/jvm/BCodeHelpers.scala | 56 ++------------- .../nsc/backend/jvm/BCodeSkelBuilder.scala | 19 ++++- .../scala/tools/nsc/backend/jvm/BTypes.scala | 22 +----- .../nsc/backend/jvm/BTypesFromSymbols.scala | 69 ++++++++++++++++++- .../nsc/backend/jvm/opt/BytecodeUtils.scala | 9 +++ .../tools/nsc/backend/jvm/opt/CallGraph.scala | 10 +-- .../backend/jvm/opt/InlineInfoAttribute.scala | 13 ---- .../tools/nsc/backend/jvm/opt/Inliner.scala | 31 +++++---- .../backend/jvm/opt/InlinerHeuristics.scala | 5 +- .../scala/tools/nsc/transform/Mixin.scala | 20 +++++- .../instrumented/InstrumentationTest.check | 2 +- test/files/run/mixin-signatures.check | 2 + test/files/run/t4891.check | 3 +- test/files/run/t5652.check | 4 +- test/files/run/t7700.check | 3 +- test/files/run/t7932.check | 4 ++ .../scala/lang/traits/BytecodeTest.scala | 9 +-- .../nsc/backend/jvm/DefaultMethodTest.scala | 5 +- .../nsc/backend/jvm/DirectCompileTest.scala | 6 +- .../nsc/backend/jvm/opt/InlinerTest.scala | 21 ++++-- .../backend/jvm/opt/ScalaInlineInfoTest.scala | 23 +++++-- .../scala/tools/testing/BytecodeTesting.scala | 15 +++- 23 files changed, 222 insertions(+), 141 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 5d152ef0e8e2..92aa75ef68f1 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -1060,12 +1060,6 @@ 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) - } - def needsInterfaceCall(sym: Symbol) = { sym.isTraitOrInterface || sym.isJavaDefined && sym.isNonBottomSubClass(definitions.ClassfileAnnotationClass) @@ -1082,7 +1076,11 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { 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) + case Super => + if (receiverClass.isTraitOrInterface) { + val staticDesc = MethodBType(typeToBType(method.owner.info) :: method.info.paramTypes.map(typeToBType), typeToBType(method.info.resultType)).descriptor + bc.invokestatic(receiverName, jname, staticDesc, pos) + } else bc.invokespecial (receiverName, jname, mdescr, 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 a5744983b280..f179c11c7ae5 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,9 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { } } + def isTraitMethodRequiringStaticImpl(sym: Symbol) = + sym.hasAttachment[global.mixer.NeedStaticImpl.type] + /** * 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 +234,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 */ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala index bddc41e5c6ac..93d6990d31ab 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala @@ -488,7 +488,24 @@ 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 (isTraitMethodRequiringStaticImpl(sym)) { + // Split concrete methods in traits (including mixin constructors) into a static method + // with an explicit this parameter, and a non-static forwarder method. + val staticDefDef = global.gen.mkStatic(dd, _.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..33a49dc63b77 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -509,7 +509,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 +530,73 @@ 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 (isTraitMethodRequiringStaticImpl(methodSym)) { + 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 = name + 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/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 d4ff6493a379..1658eadbb7de 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -9,14 +9,14 @@ 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 ByteCodeRepository.{Source, CompilationUnit} +import ByteCodeRepository.{CompilationUnit, Source} import BytecodeUtils._ class CallGraph[BT <: BTypes](val btypes: BT) { @@ -68,6 +68,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) @@ -359,7 +360,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) @@ -394,6 +395,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { samParamTypes: IntMap[btypes.ClassBType], calleeInfoWarning: Option[CalleeInfoWarning]) { override def toString = s"Callee($calleeDeclarationClass.${callee.name})" + def textifyCallee = AsmUtils.textify(callee) } /** 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 809b9e310dce..4b082d17b238 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -29,7 +29,8 @@ class Inliner[BT <: BTypes](val btypes: BT) { var inlineLog: List[InlineLog] = Nil def runInliner(): Unit = { - for (request <- collectAndOrderInlineRequests) { + val orderedRequests = collectAndOrderInlineRequests + for (request <- orderedRequests) { val Right(callee) = request.callsite.callee // collectAndOrderInlineRequests returns callsites with a known callee // TODO: if the request has downstream requests, create a snapshot to which we could roll back in case some downstream callsite cannot be inlined @@ -106,6 +107,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 +117,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 +139,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 +153,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 17807fb385ed..673c3b863314 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala @@ -7,10 +7,11 @@ package scala.tools.nsc package backend.jvm package opt -import scala.tools.asm.tree.MethodNode +import scala.tools.asm.tree.{AbstractInsnNode, MethodInsnNode, MethodNode} import scala.tools.nsc.backend.jvm.BTypes.InternalName import scala.collection.JavaConverters._ -import scala.tools.nsc.backend.jvm.BackendReporting.OptimizerWarning +import scala.tools.asm.Opcodes +import scala.tools.nsc.backend.jvm.BackendReporting.{Invalid, OptimizerWarning} class InlinerHeuristics[BT <: BTypes](val bTypes: BT) { import bTypes._ diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 6df0b992ed49..ea2bfa5bb1d0 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -143,6 +143,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // implementation class, as it's a clone that was made after erasure, and thus it does not // know its info at the beginning of erasure anymore. val sym = mixinMember cloneSymbol clazz + sym.removeAttachment[NeedStaticImpl.type] val erasureMap = erasure.erasure(mixinMember) val erasedInterfaceInfo: Type = erasureMap(mixinMember.info) @@ -1007,7 +1008,13 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { 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 +1030,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { typedPos(tree.pos)((qual DOT setter)(rhs)) - case _ => tree } @@ -1042,4 +1048,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { finally localTyper = saved } } + + private def isTraitMethodRequiringStaticImpl(dd: DefDef): Boolean = { + val sym = dd.symbol + sym != null && sym.owner.isTrait && !sym.isDeferred && + (sym.isLazy || !sym.isAccessor) && !sym.isSuperAccessor && !sym.isModule && // these are not deferred, but defDef.rhs.isEmpty + !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/run/mixin-signatures.check b/test/files/run/mixin-signatures.check index 9961992e2d1c..1cb7d54f5b68 100644 --- a/test/files/run/mixin-signatures.check +++ b/test/files/run/mixin-signatures.check @@ -1,6 +1,7 @@ class Test$bar1$ { public default java.lang.String Foo1.f(java.lang.Object) generic: public default java.lang.String Foo1.f(T) + public static java.lang.String Foo1.f(Foo1,java.lang.Object) public java.lang.Object Test$bar1$.f(java.lang.Object) public java.lang.String Test$bar1$.g(java.lang.String) public java.lang.Object Test$bar1$.g(java.lang.Object) @@ -12,6 +13,7 @@ class Test$bar1$ { class Test$bar2$ { public default java.lang.Object Foo2.f(java.lang.String) generic: public default R Foo2.f(java.lang.String) + public static java.lang.Object Foo2.f(Foo2,java.lang.String) public java.lang.Object Test$bar2$.f(java.lang.Object) public java.lang.String Test$bar2$.g(java.lang.String) public java.lang.Object Test$bar2$.g(java.lang.Object) diff --git a/test/files/run/t4891.check b/test/files/run/t4891.check index 1b1108e9eee0..3b739bc4f755 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 a0fb6fe9b4e5..6653dd47f10f 100644 --- a/test/files/run/t5652.check +++ b/test/files/run/t5652.check @@ -1,6 +1,8 @@ public default int T1.T1$$g$1() public default int T1.f0() -public default void T1.$init$() +public static int T1.T1$$g$1(T1) +public static int T1.f0(T1) +public static void T1.$init$(T1) public final int A1.A1$$g$2() public int A1.f1() public final int A2.A2$$g$1() diff --git a/test/files/run/t7700.check b/test/files/run/t7700.check index 1d51e68877ca..948bce900cd1 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 static java.lang.Object C.bar(C,java.lang.Object) public default java.lang.Object C.bar(java.lang.Object) public abstract java.lang.Object C.foo(java.lang.Object) diff --git a/test/files/run/t7932.check b/test/files/run/t7932.check index a2ad84cd4635..d3c82386bd19 100644 --- a/test/files/run/t7932.check +++ b/test/files/run/t7932.check @@ -1,6 +1,10 @@ public Category C.category() public Category C.category1() +public static Category M1.category(M1) +public static Category M1.category1(M1) public default Category M1.category() public default Category M1.category1() public default Category M2.category() public default Category M2.category1() +public static Category M2.category(M2) +public static Category M2.category1(M2) diff --git a/test/junit/scala/lang/traits/BytecodeTest.scala b/test/junit/scala/lang/traits/BytecodeTest.scala index f47fc9c12724..3e3ba386b1d6 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", false), Op(IRETURN))) } @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;", false), Op(ARETURN))) assertInvoke(getMethod(c1, "f1"), "T", "clone") assertInvoke(getMethod(c1, "f2"), "T", "clone") assertInvoke(getMethod(c1, "f3"), "C1", "clone") @@ -151,7 +152,7 @@ class BytecodeTest extends BytecodeTesting { 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(tb, "clone").filterNot(BytecodeUtils.isStaticMethod).length == 1) assert(ms(ub, "clone").isEmpty) val List(c1Clone) = ms(c1b, "clone") assertEquals(c1Clone.desc, "()Ljava/lang/Object;") 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..cc1d4a361444 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 @@ -62,7 +64,7 @@ class DirectCompileTest extends BytecodeTesting { VarOp(ILOAD, 1), Op(ICONST_0), Jump(IF_ICMPNE, - Label(7)), + Label(7)), Ldc(LDC, "a"), Op(ARETURN), Label(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 fdc17ec73f80..4ffbfa79b37a 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") @@ -1526,4 +1524,19 @@ class InlinerTest extends BytecodeTesting { val c :: _ = compileClassesSeparately(codes, extraArgs = compilerArgs) assertInvoke(getMethod(c, "t"), "p1/Implicits$RichFunction1$", "toRx$extension") } + + @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..fb49ffbce0ff 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 1a0c1e210a48..755466d52a9f 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 37874262796198bb810ec871395dbcbbe57b529d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 5 May 2016 12:47:28 +1000 Subject: [PATCH 58/58] Add impl restriction related to invokespecial to Java parents --- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 9 ++++++-- .../scala/tools/nsc/transform/Mixin.scala | 5 +++++ test/files/neg/trait-defaults-super.check | 4 ++++ test/files/neg/trait-defaults-super.scala | 21 +++++++++++++++++++ test/files/pos/trait-defaults-super.scala | 21 +++++++++++++++++++ 5 files changed, 58 insertions(+), 2 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 diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 92aa75ef68f1..6cf23b063799 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -1077,10 +1077,15 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { if (needsInterfaceCall(receiverClass)) bc.invokeinterface(receiverName, jname, mdescr, pos) else bc.invokevirtual (receiverName, jname, mdescr, pos) case Super => - if (receiverClass.isTraitOrInterface) { + if (receiverClass.isTrait && method.owner.isTrait && !method.owner.isJavaDefined) { val staticDesc = MethodBType(typeToBType(method.owner.info) :: method.info.paramTypes.map(typeToBType), typeToBType(method.info.resultType)).descriptor bc.invokestatic(receiverName, jname, staticDesc, pos) - } else bc.invokespecial (receiverName, jname, mdescr, pos) + } else { + if (receiverClass.isTraitOrInterface && !cnode.interfaces.contains(receiverName)) + reporter.error(pos, s"Implementation restriction: unable to emit a super call to ${receiverName}.${method.name} from ${cnode.name}. Add $receiverName as a direct parent of ${cnode.name}") + else + bc.invokespecial (receiverName, jname, mdescr, pos) + } } bmType.returnType diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index ea2bfa5bb1d0..2a7d410c5ffa 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -345,6 +345,11 @@ 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 => + val temp = alias1 + if (temp.owner.isJavaDefined && temp.owner.isInterface && !clazz.parentSymbols.contains(temp.owner)) { + val suggestedParent = exitingTyper(clazz.info.baseType(temp.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 } } diff --git a/test/files/neg/trait-defaults-super.check b/test/files/neg/trait-defaults-super.check new file mode 100644 index 000000000000..429de341b462 --- /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 + } +}