summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/files/neg/sammy_error_exist_no_crash.check6
-rw-r--r--test/files/neg/sammy_error_exist_no_crash.flags1
-rw-r--r--test/files/neg/sammy_error_exist_no_crash.scala6
-rw-r--r--test/files/neg/sammy_restrictions.scala28
-rw-r--r--test/files/neg/t2866.check17
-rw-r--r--test/files/neg/t2866.scala59
-rw-r--r--test/files/neg/t5639b.check4
-rw-r--r--test/files/neg/t5639b/A_1.scala17
-rw-r--r--test/files/neg/t5639b/A_2.scala11
-rw-r--r--test/files/neg/t8534.check4
-rw-r--r--test/files/neg/t8534.scala7
-rw-r--r--test/files/neg/t8534b.check4
-rw-r--r--test/files/neg/t8534b.scala4
-rw-r--r--test/files/neg/t963.check8
-rw-r--r--test/files/pos/sammy_exist.flags1
-rw-r--r--test/files/pos/sammy_exist.scala17
-rw-r--r--test/files/pos/sammy_overload.flags1
-rw-r--r--test/files/pos/sammy_overload.scala9
-rw-r--r--test/files/pos/sammy_override.flags1
-rw-r--r--test/files/pos/sammy_override.scala8
-rw-r--r--test/files/pos/t5413.scala9
-rw-r--r--test/files/pos/t5639.flags1
-rw-r--r--test/files/pos/t5639/A_1.scala17
-rw-r--r--test/files/pos/t5639/A_2.scala11
-rw-r--r--test/files/pos/t5639/Bar.scala7
-rw-r--r--test/files/pos/t5639/Foo.scala7
-rw-r--r--test/files/pos/t7750.flags1
-rw-r--r--test/files/pos/t7750.scala8
-rw-r--r--test/files/pos/t8310.flags1
-rw-r--r--test/files/pos/t8310.scala22
-rw-r--r--test/files/pos/t8954.flags1
-rw-r--r--test/files/pos/t8954/t1.scala13
-rw-r--r--test/files/pos/t8954/t2.scala39
-rw-r--r--test/files/pos/t8965.flags1
-rw-r--r--test/files/pos/t8965.scala7
-rw-r--r--test/files/run/iterator-concat.check4
-rw-r--r--test/files/run/iterator-concat.scala15
-rw-r--r--test/files/run/iterator-iterate-lazy.scala5
-rw-r--r--test/files/run/iterators.check13
-rw-r--r--test/files/run/iterators.scala136
-rw-r--r--test/files/run/sammy_repeated.check1
-rw-r--r--test/files/run/sammy_repeated.flags1
-rw-r--r--test/files/run/sammy_repeated.scala8
-rw-r--r--test/files/run/t1994.scala20
-rw-r--r--test/files/run/t2866.check3
-rw-r--r--test/files/run/t2866.scala44
-rw-r--r--test/files/run/t3516.check3
-rw-r--r--test/files/run/t3516.scala13
-rw-r--r--test/files/run/t5665.scala13
-rw-r--r--test/files/run/t6502.check8
-rw-r--r--test/files/run/t6502.scala101
-rw-r--r--test/files/run/t7407.flags2
-rw-r--r--test/files/run/t8253.check40
-rw-r--r--test/files/run/t8253.scala14
-rw-r--r--test/files/run/t8925.check2
-rw-r--r--test/files/run/t8925.flags1
-rw-r--r--test/files/run/t8925.scala31
-rw-r--r--test/files/run/t8933.check1
-rw-r--r--test/files/run/t8933/A_1.scala6
-rw-r--r--test/files/run/t8933/Test_2.scala10
-rw-r--r--test/files/run/t8933b/A.scala4
-rw-r--r--test/files/run/t8933b/Test.scala9
-rw-r--r--test/files/run/t8933c.scala14
-rw-r--r--test/files/run/t8960.scala8
-rw-r--r--test/files/t8449/Client.scala3
-rw-r--r--test/files/t8449/Test.java10
-rw-r--r--test/junit/scala/collection/IndexedSeqOptimizedTest.scala13
-rw-r--r--test/junit/scala/collection/IterableViewLikeTest.scala20
-rw-r--r--test/junit/scala/collection/IteratorTest.scala133
-rw-r--r--test/junit/scala/collection/immutable/TreeMapTest.scala20
-rw-r--r--test/junit/scala/collection/immutable/TreeSetTest.scala20
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala21
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala50
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala80
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala8
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala99
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala83
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala221
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala60
-rw-r--r--test/junit/scala/tools/testing/AssertUtil.scala20
80 files changed, 1455 insertions, 294 deletions
diff --git a/test/files/neg/sammy_error_exist_no_crash.check b/test/files/neg/sammy_error_exist_no_crash.check
new file mode 100644
index 0000000000..a0d2237ce0
--- /dev/null
+++ b/test/files/neg/sammy_error_exist_no_crash.check
@@ -0,0 +1,6 @@
+sammy_error_exist_no_crash.scala:5: error: Could not derive subclass of F[? >: String]
+ (with SAM `def method apply(s: String)Int`)
+ based on: ((x$1: String) => x$1.<parseInt: error>).
+ bar(_.parseInt)
+ ^
+one error found
diff --git a/test/files/neg/sammy_error_exist_no_crash.flags b/test/files/neg/sammy_error_exist_no_crash.flags
new file mode 100644
index 0000000000..e1b37447c9
--- /dev/null
+++ b/test/files/neg/sammy_error_exist_no_crash.flags
@@ -0,0 +1 @@
+-Xexperimental \ No newline at end of file
diff --git a/test/files/neg/sammy_error_exist_no_crash.scala b/test/files/neg/sammy_error_exist_no_crash.scala
new file mode 100644
index 0000000000..da7e47206f
--- /dev/null
+++ b/test/files/neg/sammy_error_exist_no_crash.scala
@@ -0,0 +1,6 @@
+abstract class F[T] { def apply(s: T): Int }
+
+object NeedsNiceError {
+ def bar(x: F[_ >: String]) = ???
+ bar(_.parseInt)
+} \ No newline at end of file
diff --git a/test/files/neg/sammy_restrictions.scala b/test/files/neg/sammy_restrictions.scala
index 5f1a04cd20..d003cfaf36 100644
--- a/test/files/neg/sammy_restrictions.scala
+++ b/test/files/neg/sammy_restrictions.scala
@@ -1,28 +1,28 @@
-class NoAbstract
+abstract class NoAbstract
-class TwoAbstract { def ap(a: Int): Int; def pa(a: Int): Int }
+abstract class TwoAbstract { def ap(a: Int): Int; def pa(a: Int): Int }
-class Base // check that the super class constructor isn't considered.
-class NoEmptyConstructor(a: Int) extends Base { def this(a: String) = this(0); def ap(a: Int): Int }
+abstract class Base // check that the super class constructor isn't considered.
+abstract class NoEmptyConstructor(a: Int) extends Base { def this(a: String) = this(0); def ap(a: Int): Int }
-class OneEmptyConstructor() { def this(a: Int) = this(); def ap(a: Int): Int }
+abstract class OneEmptyConstructor() { def this(a: Int) = this(); def ap(a: Int): Int }
-class OneEmptySecondaryConstructor(a: Int) { def this() = this(0); def ap(a: Int): Int }
+abstract class OneEmptySecondaryConstructor(a: Int) { def this() = this(0); def ap(a: Int): Int }
-class MultipleConstructorLists()() { def ap(a: Int): Int }
+abstract class MultipleConstructorLists()() { def ap(a: Int): Int }
-class MultipleMethodLists()() { def ap(a: Int)(): Int }
+abstract class MultipleMethodLists()() { def ap(a: Int)(): Int }
-class ImplicitConstructorParam()(implicit a: String) { def ap(a: Int): Int }
+abstract class ImplicitConstructorParam()(implicit a: String) { def ap(a: Int): Int }
-class ImplicitMethodParam() { def ap(a: Int)(implicit b: String): Int }
+abstract class ImplicitMethodParam() { def ap(a: Int)(implicit b: String): Int }
-class PolyClass[T] { def ap(a: T): T }
+abstract class PolyClass[T] { def ap(a: T): T }
-class PolyMethod { def ap[T](a: T): T }
+abstract class PolyMethod { def ap[T](a: T): T }
-class OneAbstract { def ap(a: Any): Any }
-class DerivedOneAbstract extends OneAbstract
+abstract class OneAbstract { def ap(a: Int): Any }
+abstract class DerivedOneAbstract extends OneAbstract
object Test {
implicit val s: String = ""
diff --git a/test/files/neg/t2866.check b/test/files/neg/t2866.check
new file mode 100644
index 0000000000..340fb8da22
--- /dev/null
+++ b/test/files/neg/t2866.check
@@ -0,0 +1,17 @@
+t2866.scala:30: warning: imported `one' is permanently hidden by definition of value one
+ import A.one // warning: imported `one' is permanently hidden by definition of value one.
+ ^
+t2866.scala:42: error: ambiguous implicit values:
+ both value two of type Int
+ and value one in object A of type => Int
+ match expected type Int
+ assert(implicitly[Int] == 2) // !!! Not ambiguous in 2.8.0. Ambigous in 2.7.6
+ ^
+t2866.scala:50: error: ambiguous implicit values:
+ both value two of type Int
+ and value one in object A of type => Int
+ match expected type Int
+ assert(implicitly[Int] == 2) // !!! Not ambiguous in 2.8.0. Ambiguous in 2.7.6
+ ^
+one warning found
+two errors found
diff --git a/test/files/neg/t2866.scala b/test/files/neg/t2866.scala
new file mode 100644
index 0000000000..55ebff9710
--- /dev/null
+++ b/test/files/neg/t2866.scala
@@ -0,0 +1,59 @@
+// for 2.7.x compatibility
+
+object A {
+ implicit val one = 1
+}
+
+object Test {
+
+ locally {
+ import A._
+ locally {
+ // assert(implicitly[Int] == 1) // error: could not find implicit value for parameter e: Int.
+ // !!! Why one A.one?
+ // (I assume you mean: why _not_ A.one? A.one is shadowed by local one.
+ // but the local one cannot be used yet because it does not have an explicit type.
+ implicit val one = 2
+ assert(implicitly[Int] == 2)
+ assert(one == 2)
+ }
+ }
+
+ locally {
+ import A._
+ implicit val one: Int = 2
+ assert(implicitly[Int] == 2)
+ assert(one == 2)
+ }
+
+ locally {
+ import A.one // warning: imported `one' is permanently hidden by definition of value one.
+ // !!! Really?
+ //assert(implicitly[Int] == 1)
+ implicit val one = 2
+ assert(implicitly[Int] == 2) // !!! why not 2?
+ assert(one == 2)
+ }
+
+ locally {
+ import A.one
+ assert(implicitly[Int] == 1)
+ implicit val two = 2
+ assert(implicitly[Int] == 2) // !!! Not ambiguous in 2.8.0. Ambigous in 2.7.6
+ }
+
+ locally {
+ import A._
+ assert(implicitly[Int] == 1)
+ implicit val two = 2
+ import A.{one => _}
+ assert(implicitly[Int] == 2) // !!! Not ambiguous in 2.8.0. Ambiguous in 2.7.6
+ }
+
+ locally {
+ import A.{one => _, _}
+ implicit val two = 2
+ assert(implicitly[Int] == 2) // not ambiguous in 2.8.0 nor im ambiguous in 2.7.6
+ }
+
+}
diff --git a/test/files/neg/t5639b.check b/test/files/neg/t5639b.check
new file mode 100644
index 0000000000..faa1766660
--- /dev/null
+++ b/test/files/neg/t5639b.check
@@ -0,0 +1,4 @@
+A_2.scala:6: error: could not find implicit value for parameter e: Int
+ implicitly[Int]
+ ^
+one error found
diff --git a/test/files/neg/t5639b/A_1.scala b/test/files/neg/t5639b/A_1.scala
new file mode 100644
index 0000000000..c5da10eae4
--- /dev/null
+++ b/test/files/neg/t5639b/A_1.scala
@@ -0,0 +1,17 @@
+import Implicits._
+
+class Baz
+
+object Test {
+ implicitly[Int]
+}
+
+object Implicits {
+ implicit val Baz: Int = 0
+ // This implicit was being ignored by `isQualifyingImplicit`
+ // if the classpath contained a class file for `class Baz`.
+ // This is because the package scope contains a speculative
+ // symbol for `object Baz` which is entered by `SymbolLoaders`
+ // before looking inside the class file. (A Java originated
+ // classfile results in the class/module symbol pair.)
+}
diff --git a/test/files/neg/t5639b/A_2.scala b/test/files/neg/t5639b/A_2.scala
new file mode 100644
index 0000000000..2bb36273e0
--- /dev/null
+++ b/test/files/neg/t5639b/A_2.scala
@@ -0,0 +1,11 @@
+import Implicits._
+
+class Baz
+
+object Test {
+ implicitly[Int]
+}
+
+object Implicits {
+ implicit val Baz: Int = 0
+}
diff --git a/test/files/neg/t8534.check b/test/files/neg/t8534.check
new file mode 100644
index 0000000000..297e7c1beb
--- /dev/null
+++ b/test/files/neg/t8534.check
@@ -0,0 +1,4 @@
+t8534.scala:6: error: MyTrait is not an enclosing class
+ class BugTest {def isTheBugHere(in: MyTrait.this.type#SomeData) = false}
+ ^
+one error found
diff --git a/test/files/neg/t8534.scala b/test/files/neg/t8534.scala
new file mode 100644
index 0000000000..f118d22b82
--- /dev/null
+++ b/test/files/neg/t8534.scala
@@ -0,0 +1,7 @@
+object line1 {
+ trait MyTrait
+}
+object line2 {
+ import line2._
+ class BugTest {def isTheBugHere(in: MyTrait.this.type#SomeData) = false}
+}
diff --git a/test/files/neg/t8534b.check b/test/files/neg/t8534b.check
new file mode 100644
index 0000000000..39ffa41194
--- /dev/null
+++ b/test/files/neg/t8534b.check
@@ -0,0 +1,4 @@
+t8534b.scala:3: error: stable identifier required, but foo.type found.
+ type T = foo.type#Foo
+ ^
+one error found
diff --git a/test/files/neg/t8534b.scala b/test/files/neg/t8534b.scala
new file mode 100644
index 0000000000..73b6703a9c
--- /dev/null
+++ b/test/files/neg/t8534b.scala
@@ -0,0 +1,4 @@
+object Test {
+ def foo = ""
+ type T = foo.type#Foo
+}
diff --git a/test/files/neg/t963.check b/test/files/neg/t963.check
index 4dc202c7bd..483e53c77d 100644
--- a/test/files/neg/t963.check
+++ b/test/files/neg/t963.check
@@ -1,9 +1,9 @@
-t963.scala:14: error: stable identifier required, but Test.this.y3.x found.
+t963.scala:14: error: stable identifier required, but y3.x.type found.
val w3 : y3.x.type = y3.x
- ^
-t963.scala:17: error: stable identifier required, but Test.this.y4.x found.
+ ^
+t963.scala:17: error: stable identifier required, but y4.x.type found.
val w4 : y4.x.type = y4.x
- ^
+ ^
t963.scala:10: error: type mismatch;
found : AnyRef{def x: Integer}
required: AnyRef{val x: Integer}
diff --git a/test/files/pos/sammy_exist.flags b/test/files/pos/sammy_exist.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/sammy_exist.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/sammy_exist.scala b/test/files/pos/sammy_exist.scala
new file mode 100644
index 0000000000..f05ae20463
--- /dev/null
+++ b/test/files/pos/sammy_exist.scala
@@ -0,0 +1,17 @@
+// scala> typeOf[java.util.stream.Stream[_]].nonPrivateMember(TermName("map")).info
+// [R](x$1: java.util.function.Function[_ >: T, _ <: R])java.util.stream.Stream[R]
+
+// java.util.function.Function
+trait Fun[A, B] { def apply(x: A): B }
+
+// java.util.stream.Stream
+class S[T](x: T) { def map[R](f: Fun[_ >: T, _ <: R]): R = f(x) }
+
+class Bla { def foo: Bla = this }
+
+// NOTE: inferred types show unmoored skolems, should pack them to display properly as bounded wildcards
+object T {
+ val aBlaSAM = (new S(new Bla)).map(_.foo)
+ val fun: Fun[Bla, Bla] = (x: Bla) => x
+ val aBlaSAMX = (new S(new Bla)).map(fun)
+}
diff --git a/test/files/pos/sammy_overload.flags b/test/files/pos/sammy_overload.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/sammy_overload.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/sammy_overload.scala b/test/files/pos/sammy_overload.scala
new file mode 100644
index 0000000000..5472248f4d
--- /dev/null
+++ b/test/files/pos/sammy_overload.scala
@@ -0,0 +1,9 @@
+trait Consumer[T] {
+ def consume(x: T): Unit
+}
+
+object Test {
+ def foo(x: String): Unit = ???
+ def foo(): Unit = ???
+ val f: Consumer[_ >: String] = foo
+} \ No newline at end of file
diff --git a/test/files/pos/sammy_override.flags b/test/files/pos/sammy_override.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/sammy_override.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/sammy_override.scala b/test/files/pos/sammy_override.scala
new file mode 100644
index 0000000000..a1d0651c39
--- /dev/null
+++ b/test/files/pos/sammy_override.scala
@@ -0,0 +1,8 @@
+trait IntConsumer {
+ def consume(x: Int): Unit
+}
+
+object Test {
+ def anyConsumer(x: Any): Unit = ???
+ val f: IntConsumer = anyConsumer
+} \ No newline at end of file
diff --git a/test/files/pos/t5413.scala b/test/files/pos/t5413.scala
new file mode 100644
index 0000000000..47af514a14
--- /dev/null
+++ b/test/files/pos/t5413.scala
@@ -0,0 +1,9 @@
+object Fail {
+ def nom (guard : => Boolean) (something : => Unit) { }
+ def main(args: Array[String]) {
+ nom {
+ val i = 0
+ (i != 3)
+ }()
+ }
+}
diff --git a/test/files/pos/t5639.flags b/test/files/pos/t5639.flags
new file mode 100644
index 0000000000..0acce1e7ce
--- /dev/null
+++ b/test/files/pos/t5639.flags
@@ -0,0 +1 @@
+-Xsource:2.12
diff --git a/test/files/pos/t5639/A_1.scala b/test/files/pos/t5639/A_1.scala
new file mode 100644
index 0000000000..c5da10eae4
--- /dev/null
+++ b/test/files/pos/t5639/A_1.scala
@@ -0,0 +1,17 @@
+import Implicits._
+
+class Baz
+
+object Test {
+ implicitly[Int]
+}
+
+object Implicits {
+ implicit val Baz: Int = 0
+ // This implicit was being ignored by `isQualifyingImplicit`
+ // if the classpath contained a class file for `class Baz`.
+ // This is because the package scope contains a speculative
+ // symbol for `object Baz` which is entered by `SymbolLoaders`
+ // before looking inside the class file. (A Java originated
+ // classfile results in the class/module symbol pair.)
+}
diff --git a/test/files/pos/t5639/A_2.scala b/test/files/pos/t5639/A_2.scala
new file mode 100644
index 0000000000..2bb36273e0
--- /dev/null
+++ b/test/files/pos/t5639/A_2.scala
@@ -0,0 +1,11 @@
+import Implicits._
+
+class Baz
+
+object Test {
+ implicitly[Int]
+}
+
+object Implicits {
+ implicit val Baz: Int = 0
+}
diff --git a/test/files/pos/t5639/Bar.scala b/test/files/pos/t5639/Bar.scala
deleted file mode 100644
index f577500acd..0000000000
--- a/test/files/pos/t5639/Bar.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package pack.age
-
-import pack.age.Implicits._
-
-object Quux {
- def baz : Baz = 1
-}
diff --git a/test/files/pos/t5639/Foo.scala b/test/files/pos/t5639/Foo.scala
deleted file mode 100644
index 1a07734a8e..0000000000
--- a/test/files/pos/t5639/Foo.scala
+++ /dev/null
@@ -1,7 +0,0 @@
-package pack.age
-
-class Baz
-
-object Implicits {
- implicit def Baz(n: Int): Baz = new Baz
-}
diff --git a/test/files/pos/t7750.flags b/test/files/pos/t7750.flags
new file mode 100644
index 0000000000..b216e74c97
--- /dev/null
+++ b/test/files/pos/t7750.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -feature
diff --git a/test/files/pos/t7750.scala b/test/files/pos/t7750.scala
new file mode 100644
index 0000000000..befec76949
--- /dev/null
+++ b/test/files/pos/t7750.scala
@@ -0,0 +1,8 @@
+trait LazyCombiner[Elem, +To, Buff <: Growable[Elem] with Sizing]
+trait Growable[T]
+trait Sizing
+
+
+object Test {
+ null.isInstanceOf[LazyCombiner[_, _, _]] // issued an existential feature warning
+}
diff --git a/test/files/pos/t8310.flags b/test/files/pos/t8310.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/t8310.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/t8310.scala b/test/files/pos/t8310.scala
new file mode 100644
index 0000000000..874caf4d3b
--- /dev/null
+++ b/test/files/pos/t8310.scala
@@ -0,0 +1,22 @@
+trait Comparinator[T] { def compare(a: T, b: T): Int }
+
+object TestOkay {
+ def sort(x: Comparinator[_ >: String]) = ()
+ sort((a: String, b: String) => a.compareToIgnoreCase(b))
+}
+
+object TestOkay2 {
+ def sort[T](x: Comparinator[_ >: T]) = ()
+ sort((a: String, b: String) => a.compareToIgnoreCase(b))
+}
+
+object TestOkay3 {
+ def sort[T](xs: Option[T], x: Comparinator[_ >: T]) = ()
+ sort(Some(""), (a: String, b: String) => a.compareToIgnoreCase(b))
+}
+
+object TestKoOverloaded {
+ def sort[T](xs: Option[T]) = ()
+ def sort[T](xs: Option[T], x: Comparinator[_ >: T]) = ()
+ sort(Some(""), (a: String, b: String) => a.compareToIgnoreCase(b))
+}
diff --git a/test/files/pos/t8954.flags b/test/files/pos/t8954.flags
new file mode 100644
index 0000000000..7de3c0f3ee
--- /dev/null
+++ b/test/files/pos/t8954.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -deprecation
diff --git a/test/files/pos/t8954/t1.scala b/test/files/pos/t8954/t1.scala
new file mode 100644
index 0000000000..3986d9f3b5
--- /dev/null
+++ b/test/files/pos/t8954/t1.scala
@@ -0,0 +1,13 @@
+package scala.foo
+
+// 1. a class about to be made final
+@deprecatedInheritance class A {
+ def foo(): Unit = ???
+}
+
+// 1.1:
+// - no inheritance warning because same file
+// - no "override non-deprecated member" because @deprecatedInheritance
+class B2 extends A {
+ @deprecated("","") override def foo(): Unit = ???
+}
diff --git a/test/files/pos/t8954/t2.scala b/test/files/pos/t8954/t2.scala
new file mode 100644
index 0000000000..4def127832
--- /dev/null
+++ b/test/files/pos/t8954/t2.scala
@@ -0,0 +1,39 @@
+package scala.foo
+
+// 1.2 deprecated children should be fine...
+@deprecated("", "") class B extends A {
+
+ // 1.3 and shouldn't trigger the
+ // "overriding non-deprecated parent" warning
+ override def foo(): Unit = ???
+}
+
+@deprecated("","") class F {
+ // 1.4 a class inside a deprecated class should work too
+ class G extends A
+}
+
+// 2. a method about to be made final
+class C {
+ @deprecatedOverriding def foo(): Unit = ???
+}
+
+// 2.1 overriding with a deprecated def should be fine
+// and also shoudln't trigger the "deprecation is useless"
+// warning
+class D extends C {
+ @deprecated("","") override def foo(): Unit = ???
+}
+
+// 2.2 overriding from a deprecated class should be fine
+@deprecated("","") class E extends C {
+ override def foo(): Unit = ???
+}
+
+// 2.3 overriding from deeper inside a deprecated class
+// should work too
+@deprecated("","") class H {
+ class I extends C {
+ override def foo(): Unit = ???
+ }
+}
diff --git a/test/files/pos/t8965.flags b/test/files/pos/t8965.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/pos/t8965.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/pos/t8965.scala b/test/files/pos/t8965.scala
new file mode 100644
index 0000000000..4f39330f4e
--- /dev/null
+++ b/test/files/pos/t8965.scala
@@ -0,0 +1,7 @@
+class A {
+ def f(x: Any with AnyRef, y: Any with AnyRef) = x eq y
+ // a.scala:2: warning: Any and Any are unrelated: they will most likely never compare equal
+ // def f(x: Any with AnyRef, y: Any with AnyRef) = x eq y
+ // ^
+ // one warning found
+}
diff --git a/test/files/run/iterator-concat.check b/test/files/run/iterator-concat.check
deleted file mode 100644
index 23835b07ae..0000000000
--- a/test/files/run/iterator-concat.check
+++ /dev/null
@@ -1,4 +0,0 @@
-100
-1000
-10000
-100000
diff --git a/test/files/run/iterator-concat.scala b/test/files/run/iterator-concat.scala
deleted file mode 100644
index f11363410f..0000000000
--- a/test/files/run/iterator-concat.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-object Test {
- // Create `size` Function0s, each of which evaluates to an Iterator
- // which produces 1. Then fold them over ++ to get a single iterator,
- // which should sum to "size".
- def mk(size: Int): Iterator[Int] = {
- val closures = (1 to size).toList.map(x => (() => Iterator(1)))
- closures.foldLeft(Iterator.empty: Iterator[Int])((res, f) => res ++ f())
- }
- def main(args: Array[String]): Unit = {
- println(mk(100).sum)
- println(mk(1000).sum)
- println(mk(10000).sum)
- println(mk(100000).sum)
- }
-}
diff --git a/test/files/run/iterator-iterate-lazy.scala b/test/files/run/iterator-iterate-lazy.scala
deleted file mode 100644
index 92b170062e..0000000000
--- a/test/files/run/iterator-iterate-lazy.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-object Test {
- def main(args: Array[String]): Unit = {
- Iterator.iterate((1 to 5).toList)(_.tail).takeWhile(_.nonEmpty).map(_.head).toList
- }
-}
diff --git a/test/files/run/iterators.check b/test/files/run/iterators.check
deleted file mode 100644
index bb139c1610..0000000000
--- a/test/files/run/iterators.check
+++ /dev/null
@@ -1,13 +0,0 @@
-test check_from was successful
-test check_range was successful
-test check_range2 was successful
-test check_range3 was successful
-test check_take was successful
-test check_drop was successful
-test check_foreach was successful
-test check_forall was successful
-test check_fromArray was successful
-test check_toSeq was successful
-test check_indexOf was successful
-test check_findIndexOf was successful
-
diff --git a/test/files/run/iterators.scala b/test/files/run/iterators.scala
deleted file mode 100644
index 57e05d3472..0000000000
--- a/test/files/run/iterators.scala
+++ /dev/null
@@ -1,136 +0,0 @@
-//############################################################################
-// Iterators
-//############################################################################
-
-//############################################################################
-
-import scala.language.postfixOps
-
-object Test {
-
- def check_from: Int = {
- val it1 = Iterator.from(-1)
- val it2 = Iterator.from(0, -1)
- it1.next + it2.next
- }
-
- def check_range: Int = {
- val xs1 = Iterator.range(0, 10, 2) toList;
- val xs2 = Iterator.range(0, 10, -2) toList;
- val xs3 = Iterator.range(10, 0, -2) toList;
- val xs4 = Iterator.range(10, 0, 2) toList;
- val xs5 = Iterator.range(0, 10, 11) toList;
- xs1.length + xs2.length + xs3.length + xs4.length + xs5.length
- }
-
- def check_range2: Int = {
- val r1start = 0
- val r1end = 10
- val r1step = 1
- val r1 = Iterator.range(r1start, r1end, r1step) toList;
- val r2 = Iterator.range(r1start, r1end, r1step + 1) toList;
- val r3 = Iterator.range(r1end, r1start, -r1step) toList;
- val r4 = Iterator.range(0, 10, 11) toList;
- // 10 + 5 + 10 + 1
- r1.length + r2.length + r3.length + r4.length
- }
-
- def check_range3: Int = {
- def trues(xs: List[Boolean]) = xs.foldLeft(0)((a, b) => if (b) a+1 else a)
- val r1 = Iterator.range(0, 10)
- val xs1 = List(r1 contains 5, r1 contains 6)
- val r2a = Iterator.range(0, 10, 2)
- val r2b = Iterator.range(0, 10, 2)
- val xs2 = List(r2a contains 5, r2b contains 6)
- val r3 = Iterator.range(0, 10, 11)
- val xs3 = List(r3 contains 5, r3 contains 6)
- // 2 + 1 + 0
- trues(xs1) + trues(xs2) + trues(xs3)
- }
-
- def check_take: Int = {
- val it1 = Iterator.from(0)
- val xs1 = it1 take 10 toList;
- xs1.length
- }
-
- def check_drop: Int = {
- val it1 = Iterator.from(0)
- val it2 = it1 map { 2 * _ }
- val n1 = it1 drop 2 next
- val n2 = it2 drop 2 next;
- n1 + n2
- }
-
- def check_foreach: Int = {
- val it1 = Iterator.from(0) take 20
- var n = 0
- it1 foreach { n += _ }
- n
- }
-
- def check_forall: Int = {
- val it1 = Iterator.from(0)
- val it2 = Iterator.from(1)
- 0
- }
-
- def check_fromArray: Int = { // ticket #429
- val a = List(1, 2, 3, 4).toArray
- var xs0 = a.iterator.toList;
- var xs1 = a.slice(0, 1).iterator.toList;
- var xs2 = a.slice(0, 2).iterator.toList;
- var xs3 = a.slice(0, 3).iterator.toList;
- var xs4 = a.slice(0, 4).iterator.toList;
- xs0.length + xs1.length + xs2.length + xs3.length + xs4.length
- }
-
- def check_toSeq: String =
- List(1, 2, 3, 4, 5).iterator.toSeq.mkString("x")
-
- def check_indexOf: String = {
- val i = List(1, 2, 3, 4, 5).indexOf(4)
- val j = List(1, 2, 3, 4, 5).indexOf(16)
- "" + i + "x" + j
- }
-
- def check_findIndexOf: String = {
- val i = List(1, 2, 3, 4, 5).indexWhere { x: Int => x >= 4 }
- val j = List(1, 2, 3, 4, 5).indexWhere { x: Int => x >= 16 }
- "" + i + "x" + j
- }
-
- def check_success[A](name: String, closure: => A, expected: A) {
- print("test " + name)
- try {
- val actual: A = closure
- if (actual == expected)
- print(" was successful")
- else
- print(" failed: expected "+ expected +", found "+ actual)
- }
- catch {
- case exception: Throwable =>
- print(" raised exception " + exception)
- }
- println()
- }
-
- def main(args: Array[String]) {
- check_success("check_from", check_from, -1)
- check_success("check_range", check_range, 11)
- check_success("check_range2", check_range2, 26)
- check_success("check_range3", check_range3, 3)
- check_success("check_take", check_take, 10)
- check_success("check_drop", check_drop, 12)
- check_success("check_foreach", check_foreach, 190)
- check_success("check_forall", check_forall, 0)
- check_success("check_fromArray",check_fromArray, 14)
- check_success("check_toSeq", check_toSeq, "1x2x3x4x5")
- check_success("check_indexOf", check_indexOf, "3x-1")
- check_success("check_findIndexOf", check_findIndexOf, "3x-1")
- println()
- }
-}
-
-//############################################################################
diff --git a/test/files/run/sammy_repeated.check b/test/files/run/sammy_repeated.check
new file mode 100644
index 0000000000..1cff0f067c
--- /dev/null
+++ b/test/files/run/sammy_repeated.check
@@ -0,0 +1 @@
+WrappedArray(1)
diff --git a/test/files/run/sammy_repeated.flags b/test/files/run/sammy_repeated.flags
new file mode 100644
index 0000000000..e1b37447c9
--- /dev/null
+++ b/test/files/run/sammy_repeated.flags
@@ -0,0 +1 @@
+-Xexperimental \ No newline at end of file
diff --git a/test/files/run/sammy_repeated.scala b/test/files/run/sammy_repeated.scala
new file mode 100644
index 0000000000..c24dc41909
--- /dev/null
+++ b/test/files/run/sammy_repeated.scala
@@ -0,0 +1,8 @@
+trait RepeatedSink { def accept(a: Any*): Unit }
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val f: RepeatedSink = (a) => println(a)
+ f.accept(1)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t1994.scala b/test/files/run/t1994.scala
new file mode 100644
index 0000000000..0b463e3444
--- /dev/null
+++ b/test/files/run/t1994.scala
@@ -0,0 +1,20 @@
+class A {
+ protected def x = 0
+ protected[A] def y = 0
+}
+
+class B extends A {
+ override def x = 1
+ def superY = super[A].y
+ override def y = 1
+}
+
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val b = new B
+ assert(b.x == 1)
+ assert(b.y == 1)
+ assert(b.superY == 0)
+ }
+}
diff --git a/test/files/run/t2866.check b/test/files/run/t2866.check
new file mode 100644
index 0000000000..7f52da85fb
--- /dev/null
+++ b/test/files/run/t2866.check
@@ -0,0 +1,3 @@
+t2866.scala:30: warning: imported `one' is permanently hidden by definition of value one
+ import A.one // warning: imported `one' is permanently hidden by definition of value one.
+ ^
diff --git a/test/files/run/t2866.scala b/test/files/run/t2866.scala
new file mode 100644
index 0000000000..8059107583
--- /dev/null
+++ b/test/files/run/t2866.scala
@@ -0,0 +1,44 @@
+// for 2.7.x compatibility
+
+object A {
+ implicit val one = 1
+}
+
+object Test extends App {
+
+ locally {
+ import A._
+ locally {
+ // assert(implicitly[Int] == 1) // error: could not find implicit value for parameter e: Int.
+ // !!! Why one A.one?
+ // (I assume you mean: why _not_ A.one? A.one is shadowed by local one.
+ // but the local one cannot be used yet because it does not have an explicit type.
+ implicit val one = 2
+ assert(implicitly[Int] == 2)
+ assert(one == 2)
+ }
+ }
+
+ locally {
+ import A._
+ implicit val one: Int = 2
+ assert(implicitly[Int] == 2)
+ assert(one == 2)
+ }
+
+ locally {
+ import A.one // warning: imported `one' is permanently hidden by definition of value one.
+ // !!! Really?
+ //assert(implicitly[Int] == 1)
+ implicit val one = 2
+ assert(implicitly[Int] == 2) // !!! why not 2?
+ assert(one == 2)
+ }
+
+ locally {
+ import A.{one => _, _}
+ implicit val two = 2
+ assert(implicitly[Int] == 2) // not ambiguous in 2.8.0 nor im ambiguous in 2.7.6
+ }
+
+}
diff --git a/test/files/run/t3516.check b/test/files/run/t3516.check
deleted file mode 100644
index d0d10d82fa..0000000000
--- a/test/files/run/t3516.check
+++ /dev/null
@@ -1,3 +0,0 @@
-1
-1
-21
diff --git a/test/files/run/t3516.scala b/test/files/run/t3516.scala
deleted file mode 100644
index aa302ce85a..0000000000
--- a/test/files/run/t3516.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-object Test {
- def mkIterator = (1 to 5).iterator map (x => { println(x) ; x })
- def mkInfinite = Iterator continually { println(1) ; 1 }
-
- def main(args: Array[String]): Unit = {
- // Stream is strict in its head so we should see 1 from each of them.
- val s1 = mkIterator.toStream
- val s2 = mkInfinite.toStream
- // back and forth without slipping into nontermination.
- println((Stream from 1).toIterator.drop(10).toStream.drop(10).toIterator.next)
- ()
- }
-}
diff --git a/test/files/run/t5665.scala b/test/files/run/t5665.scala
new file mode 100644
index 0000000000..3ac498b5c0
--- /dev/null
+++ b/test/files/run/t5665.scala
@@ -0,0 +1,13 @@
+object O {
+ trait T {
+ private[this] val c: Int = 42
+ def f =
+ { x: Int => c }
+ }
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ assert(new O.T{}.f(0) == 42)
+ }
+}
diff --git a/test/files/run/t6502.check b/test/files/run/t6502.check
new file mode 100644
index 0000000000..95d36ee221
--- /dev/null
+++ b/test/files/run/t6502.check
@@ -0,0 +1,8 @@
+test1 res1: true
+test1 res2: true
+test2 res1: true
+test2 res2: true
+test3 res1: true
+test3 res2: true
+test4 res1: true
+test4 res2: true
diff --git a/test/files/run/t6502.scala b/test/files/run/t6502.scala
new file mode 100644
index 0000000000..ced1b5812d
--- /dev/null
+++ b/test/files/run/t6502.scala
@@ -0,0 +1,101 @@
+import scala.tools.partest._
+import java.io.File
+import scala.tools.nsc.interpreter.ILoop
+
+object Test extends StoreReporterDirectTest {
+ def code = ???
+
+ def compileCode(code: String, jarFileName: String) = {
+ val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator")
+ compileString(newCompiler("-cp", classpath, "-d", s"${testOutput.path}/$jarFileName"))(code)
+ }
+
+ def app1 = """
+ package test
+
+ object Test extends App {
+ def test(): Unit = {
+ println("testing...")
+ }
+ }"""
+
+ def app2 = """
+ package test
+
+ object Test extends App {
+ def test(): Unit = {
+ println("testing differently...")
+ }
+ }"""
+
+ def app3 = """
+ package test
+
+ object Test3 extends App {
+ def test(): Unit = {
+ println("new object in existing package")
+ }
+ }"""
+
+ def test1(): Unit = {
+ val jar = "test1.jar"
+ compileCode(app1, jar)
+
+ val output = ILoop.run(List(s":require ${testOutput.path}/$jar", "test.Test.test()"))
+ val lines = output.split("\n")
+ val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
+ val res2 = lines(lines.length-3).contains("testing...")
+
+ println(s"test1 res1: $res1")
+ println(s"test1 res2: $res2")
+ }
+
+ def test2(): Unit = {
+ // should reject jars with conflicting entries
+ val jar1 = "test1.jar"
+ val jar2 = "test2.jar"
+ compileCode(app2, jar2)
+
+ val output = ILoop.run(List(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar2"))
+ val lines = output.split("\n")
+ val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
+ val res2 = lines(lines.length-3).contains("test2.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
+
+ println(s"test2 res1: $res1")
+ println(s"test2 res2: $res2")
+ }
+
+ def test3(): Unit = {
+ // should accept jars with overlapping packages, but no conflicts
+ val jar1 = "test1.jar"
+ val jar3 = "test3.jar"
+ compileCode(app3, jar3)
+
+ val output = ILoop.run(List(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar3", "test.Test3.test()"))
+ val lines = output.split("\n")
+ val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
+ val res2 = lines(lines.length-3).contains("new object in existing package")
+
+ println(s"test3 res1: $res1")
+ println(s"test3 res2: $res2")
+ }
+
+ def test4(): Unit = {
+ // twice the same jar should be rejected
+ val jar1 = "test1.jar"
+ val output = ILoop.run(List(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar1"))
+ val lines = output.split("\n")
+ val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
+ val res2 = lines(lines.length-3).contains("test1.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
+
+ println(s"test4 res1: $res1")
+ println(s"test4 res2: $res2")
+ }
+
+ def show(): Unit = {
+ test1()
+ test2()
+ test3()
+ test4()
+ }
+}
diff --git a/test/files/run/t7407.flags b/test/files/run/t7407.flags
index c8547a27dc..be4ef0798a 100644
--- a/test/files/run/t7407.flags
+++ b/test/files/run/t7407.flags
@@ -1 +1 @@
--Ynooptimise -Ybackend:GenBCode
+-Ynooptimise -Yopt:l:none -Ybackend:GenBCode
diff --git a/test/files/run/t8253.check b/test/files/run/t8253.check
new file mode 100644
index 0000000000..0b4cb2d1f7
--- /dev/null
+++ b/test/files/run/t8253.check
@@ -0,0 +1,40 @@
+
+<sample xmlns='ns1'/>
+{
+ var $tmpscope: _root_.scala.xml.NamespaceBinding = $scope;
+ $tmpscope = new _root_.scala.xml.NamespaceBinding(null, "ns1", $tmpscope);
+ {
+ val $scope: _root_.scala.xml.NamespaceBinding = $tmpscope;
+ new _root_.scala.xml.Elem(null, "sample", _root_.scala.xml.Null, $scope, true)
+ }
+}
+
+<sample xmlns={identity(ns1)}/>
+{
+ var $tmpscope: _root_.scala.xml.NamespaceBinding = $scope;
+ $tmpscope = new _root_.scala.xml.NamespaceBinding(null, ns1, $tmpscope);
+ {
+ val $scope: _root_.scala.xml.NamespaceBinding = $tmpscope;
+ new _root_.scala.xml.Elem(null, "sample", _root_.scala.xml.Null, $scope, true)
+ }
+}
+
+<sample xmlns:foo='ns1'/>
+{
+ var $tmpscope: _root_.scala.xml.NamespaceBinding = $scope;
+ $tmpscope = new _root_.scala.xml.NamespaceBinding("foo", "ns1", $tmpscope);
+ {
+ val $scope: _root_.scala.xml.NamespaceBinding = $tmpscope;
+ new _root_.scala.xml.Elem(null, "sample", _root_.scala.xml.Null, $scope, true)
+ }
+}
+
+<sample xmlns:foo={identity(ns1)}/>
+{
+ var $tmpscope: _root_.scala.xml.NamespaceBinding = $scope;
+ $tmpscope = new _root_.scala.xml.NamespaceBinding("foo", ns1, $tmpscope);
+ {
+ val $scope: _root_.scala.xml.NamespaceBinding = $tmpscope;
+ new _root_.scala.xml.Elem(null, "sample", _root_.scala.xml.Null, $scope, true)
+ }
+}
diff --git a/test/files/run/t8253.scala b/test/files/run/t8253.scala
new file mode 100644
index 0000000000..c4800b4491
--- /dev/null
+++ b/test/files/run/t8253.scala
@@ -0,0 +1,14 @@
+object Test extends App {
+ import reflect.runtime.universe._ // not using the XML library in compiler tests
+
+ def show(code: String, t: Tree) = println(s"\n$code\n$t")
+
+ val ns1 = "ns1"
+ show("<sample xmlns='ns1'/>", q"<sample xmlns='ns1'/>")
+ show("<sample xmlns={identity(ns1)}/>", q"<sample xmlns={ns1}/>")
+ show("<sample xmlns:foo='ns1'/>", q"<sample xmlns:foo='ns1'/>")
+ show("<sample xmlns:foo={identity(ns1)}/>", q"<sample xmlns:foo={ns1}/>")
+
+ // `identity(foo)` used to match the overly permissive match in SymbolXMLBuilder
+ // which was intented to more specifically match `_root_.scala.xml.Text(...)`
+}
diff --git a/test/files/run/t8925.check b/test/files/run/t8925.check
new file mode 100644
index 0000000000..112e7005df
--- /dev/null
+++ b/test/files/run/t8925.check
@@ -0,0 +1,2 @@
+bar
+abcd
diff --git a/test/files/run/t8925.flags b/test/files/run/t8925.flags
new file mode 100644
index 0000000000..be4ef0798a
--- /dev/null
+++ b/test/files/run/t8925.flags
@@ -0,0 +1 @@
+-Ynooptimise -Yopt:l:none -Ybackend:GenBCode
diff --git a/test/files/run/t8925.scala b/test/files/run/t8925.scala
new file mode 100644
index 0000000000..33f4505f03
--- /dev/null
+++ b/test/files/run/t8925.scala
@@ -0,0 +1,31 @@
+object Ex {
+ def unapply(t: Throwable): Option[Throwable] = Some(t)
+}
+
+class A {
+ var x = ""
+
+ def bar =
+ try {
+ "bar"
+ } finally {
+ try {
+ x += "a"
+ } finally {
+ x += "b"
+ try {
+ x += "c"
+ throw null
+ } catch {
+ case Ex(_) =>
+ x += "d"
+ }
+ }
+ }
+}
+
+object Test extends App {
+ val a = new A
+ println(a.bar)
+ println(a.x)
+}
diff --git a/test/files/run/t8933.check b/test/files/run/t8933.check
new file mode 100644
index 0000000000..d5ef468b98
--- /dev/null
+++ b/test/files/run/t8933.check
@@ -0,0 +1 @@
+'traitSymbol
diff --git a/test/files/run/t8933/A_1.scala b/test/files/run/t8933/A_1.scala
new file mode 100644
index 0000000000..996e3b4a2c
--- /dev/null
+++ b/test/files/run/t8933/A_1.scala
@@ -0,0 +1,6 @@
+class MotherClass
+
+trait MixinWithSymbol {
+ self: MotherClass =>
+ def symbolFromTrait: Symbol = 'traitSymbol
+}
diff --git a/test/files/run/t8933/Test_2.scala b/test/files/run/t8933/Test_2.scala
new file mode 100644
index 0000000000..c506a7c51f
--- /dev/null
+++ b/test/files/run/t8933/Test_2.scala
@@ -0,0 +1,10 @@
+class MotherClass extends MixinWithSymbol {
+ val classSymbol = 'classSymbol
+}
+
+object Test {
+ def main(args: Array[String]) {
+ val symbol = (new MotherClass).symbolFromTrait
+ println(symbol)
+ }
+}
diff --git a/test/files/run/t8933b/A.scala b/test/files/run/t8933b/A.scala
new file mode 100644
index 0000000000..d25d893c6f
--- /dev/null
+++ b/test/files/run/t8933b/A.scala
@@ -0,0 +1,4 @@
+trait MixinWithSymbol {
+ self: MotherClass =>
+ def symbolFromTrait: Any = 'traitSymbol
+}
diff --git a/test/files/run/t8933b/Test.scala b/test/files/run/t8933b/Test.scala
new file mode 100644
index 0000000000..46eedd660f
--- /dev/null
+++ b/test/files/run/t8933b/Test.scala
@@ -0,0 +1,9 @@
+class MotherClass extends MixinWithSymbol {
+ def foo = 'sym1
+}
+
+object Test {
+ def main(args: Array[String]) {
+ (new MotherClass).symbolFromTrait
+ }
+}
diff --git a/test/files/run/t8933c.scala b/test/files/run/t8933c.scala
new file mode 100644
index 0000000000..22011bc323
--- /dev/null
+++ b/test/files/run/t8933c.scala
@@ -0,0 +1,14 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ try {
+ {throw T; Symbol}.apply("a")
+ assert(false, "exception not thrown")
+ } catch {
+ case T => // ok
+ case t: Throwable =>
+ assert(false, "wrong not thrown: " + t)
+ }
+ }
+}
+
+object T extends Throwable
diff --git a/test/files/run/t8960.scala b/test/files/run/t8960.scala
index c6bcd0770c..a58ac53d33 100644
--- a/test/files/run/t8960.scala
+++ b/test/files/run/t8960.scala
@@ -1,6 +1,12 @@
object Test extends App {
def test(o: AnyRef, sp: Boolean = false) = {
- if (sp) assert(o.getClass.getSuperclass.getName contains "$sp")
+ val isSpecialized = o.getClass.getSuperclass.getName contains "$sp"
+ val isDelambdafyMethod = o.getClass.getName contains "$lambda$"
+ assert(
+ // delambdafy:method doesn't currently emit specialized anonymous function classes
+ if (sp) (isSpecialized || isDelambdafyMethod) else !isSpecialized,
+ o.getClass.getName)
+
val Some(f) = o.getClass.getDeclaredFields.find(_.getName == "serialVersionUID")
assert(f.getLong(null) == 0l)
}
diff --git a/test/files/t8449/Client.scala b/test/files/t8449/Client.scala
new file mode 100644
index 0000000000..5d273f06b2
--- /dev/null
+++ b/test/files/t8449/Client.scala
@@ -0,0 +1,3 @@
+object Client {
+ def foo: Any = new Test().foo
+}
diff --git a/test/files/t8449/Test.java b/test/files/t8449/Test.java
new file mode 100644
index 0000000000..ecb1711b24
--- /dev/null
+++ b/test/files/t8449/Test.java
@@ -0,0 +1,10 @@
+public class Test {
+ // Raw type over a Scala type constructor
+ public scala.Function1 foo() { return null; }
+ // scalac reported:
+ // % scalac-hash v2.11.2 -d /tmp sandbox/{Test.java,Client.scala}
+ // sandbox/Test.java:2: error: trait Function1 takes type parameters
+ // public scala.Function1 foo() { return null; }
+ // ^
+ // one error found
+}
diff --git a/test/junit/scala/collection/IndexedSeqOptimizedTest.scala b/test/junit/scala/collection/IndexedSeqOptimizedTest.scala
index e5382907af..419e1454cb 100644
--- a/test/junit/scala/collection/IndexedSeqOptimizedTest.scala
+++ b/test/junit/scala/collection/IndexedSeqOptimizedTest.scala
@@ -13,4 +13,17 @@ class IndexedSeqOptimizedTest {
assertEquals(0, (Array(2): collection.mutable.WrappedArray[Int]).lastIndexWhere(_ => true, 1))
assertEquals(2, "abc123".lastIndexWhere(_.isLetter, 6))
}
+
+ @Test
+ def hasCorrectDropAndTakeMethods() {
+ assertEquals("", "abc" take Int.MinValue)
+ assertEquals("", "abc" takeRight Int.MinValue)
+ assertEquals("abc", "abc" drop Int.MinValue)
+ assertEquals("abc", "abc" dropRight Int.MinValue)
+
+ assertArrayEquals(Array.empty[Int], Array(1, 2, 3) take Int.MinValue)
+ assertArrayEquals(Array.empty[Int], Array(1, 2, 3) takeRight Int.MinValue)
+ assertArrayEquals(Array(1, 2, 3), Array(1, 2, 3) drop Int.MinValue)
+ assertArrayEquals(Array(1, 2, 3), Array(1, 2, 3) dropRight Int.MinValue)
+ }
}
diff --git a/test/junit/scala/collection/IterableViewLikeTest.scala b/test/junit/scala/collection/IterableViewLikeTest.scala
new file mode 100644
index 0000000000..55da02744b
--- /dev/null
+++ b/test/junit/scala/collection/IterableViewLikeTest.scala
@@ -0,0 +1,20 @@
+package scala.collection
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class IterableViewLikeTest {
+
+ @Test
+ def hasCorrectDropAndTakeMethods() {
+ val iter = Iterable(1, 2, 3)
+
+ assertEquals(Iterable.empty[Int], iter.view take Int.MinValue force)
+ assertEquals(Iterable.empty[Int], iter.view takeRight Int.MinValue force)
+ assertEquals(iter, iter.view drop Int.MinValue force)
+ assertEquals(iter, iter.view dropRight Int.MinValue force)
+ }
+}
diff --git a/test/junit/scala/collection/IteratorTest.scala b/test/junit/scala/collection/IteratorTest.scala
index b7a9805c9f..d5389afd0c 100644
--- a/test/junit/scala/collection/IteratorTest.scala
+++ b/test/junit/scala/collection/IteratorTest.scala
@@ -6,11 +6,14 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import scala.tools.testing.AssertUtil._
+
+import Seq.empty
+
@RunWith(classOf[JUnit4])
class IteratorTest {
- @Test
- def groupedIteratorShouldNotAskForUnneededElement(): Unit = {
+ @Test def groupedIteratorShouldNotAskForUnneededElement(): Unit = {
var counter = 0
val it = new Iterator[Int] { var i = 0 ; def hasNext = { counter = i; true } ; def next = { i += 1; i } }
val slidingIt = it sliding 2
@@ -25,4 +28,130 @@ class IteratorTest {
slidingIt.next
assertEquals("Counter should be one, that means we didn't look further than needed", 1, counter)
}
+
+ @Test def dropDoesNotGrowStack(): Unit = {
+ def it = new Iterator[Throwable] { def hasNext = true ; def next = new Throwable }
+
+ assertEquals(it.drop(1).next.getStackTrace.length, it.drop(1).drop(1).next.getStackTrace.length)
+ }
+
+ @Test def dropIsChainable(): Unit = {
+ assertSameElements(1 to 4, Iterator from 0 take 5 drop 1)
+ assertSameElements(3 to 4, Iterator from 0 take 5 drop 3)
+ assertSameElements(empty, Iterator from 0 take 5 drop 5)
+ assertSameElements(empty, Iterator from 0 take 5 drop 10)
+ assertSameElements(0 to 4, Iterator from 0 take 5 drop 0)
+ assertSameElements(0 to 4, Iterator from 0 take 5 drop -1)
+ assertSameElements(2 to 8 by 2, Iterator from 0 take 5 drop 1 map (2 * _))
+ assertSameElements(2 to 8 by 2, Iterator from 0 take 5 map (2 * _) drop 1)
+ assertSameElements(3 to 4, Iterator from 0 take 5 drop 1 drop 2)
+ assertSameElements(3 to 4, Iterator from 0 take 5 drop 2 drop 1)
+ }
+
+ @Test def sliceIsChainable(): Unit = {
+ assertSameElements(3 to 6, Iterator from 0 slice (3, 7))
+ assertSameElements(empty, Iterator from 0 slice (3, 3))
+ assertSameElements(0 to 2, Iterator from 0 slice (-1, 3))
+ assertSameElements(empty, Iterator from 0 slice (3, -1))
+ assertSameElements(6 to 12 by 2, Iterator from 0 slice (3, 7) map (2 * _))
+ assertSameElements(6 to 12 by 2, Iterator from 0 map (2 * _) slice (3, 7))
+ assertSameElements(4 to 6, Iterator from 0 slice (3, 7) drop 1)
+ assertSameElements(4 to 7, Iterator from 0 drop 1 slice (3, 7))
+ assertSameElements(4 to 5, Iterator from 0 slice (3, 7) slice (1, 3))
+ assertSameElements(4 to 6, Iterator from 0 slice (3, 7) slice (1, 10))
+ }
+
+ // test/files/run/iterator-concat.scala
+ @Test def concatIsStackFriendly(): Unit = {
+ // Create `size` Function0s, each of which evaluates to an Iterator
+ // which produces 1. Then fold them over ++ to get a single iterator,
+ // which should sum to "size".
+ def mk(size: Int): Iterator[Int] = {
+ //val closures = (1 to size).toList.map(x => (() => Iterator(1)))
+ //closures.foldLeft(Iterator.empty: Iterator[Int])((res, f) => res ++ f())
+ List.fill(size)(() => Iterator(1)).foldLeft(Iterator.empty: Iterator[Int])((res, f) => res ++ f())
+ }
+ assertEquals(100, mk(100).sum)
+ assertEquals(1000, mk(1000).sum)
+ assertEquals(10000, mk(10000).sum)
+ assertEquals(100000, mk(100000).sum)
+ }
+
+ @Test def from(): Unit = {
+ val it1 = Iterator.from(-1)
+ val it2 = Iterator.from(0, -1)
+ assertEquals(-1, it1.next())
+ assertEquals(0, it2.next())
+ }
+ @Test def range(): Unit = {
+ assertEquals(5, Iterator.range(0, 10, 2).size)
+ assertEquals(0, Iterator.range(0, 10, -2).size)
+ assertEquals(5, Iterator.range(10, 0, -2).size)
+ assertEquals(0, Iterator.range(10, 0, 2).size)
+ assertEquals(1, Iterator.range(0, 10, 11).size)
+ assertEquals(10, Iterator.range(0, 10, 1).size)
+ assertEquals(10, Iterator.range(10, 0, -1).size)
+ }
+ @Test def range3(): Unit = {
+ val r1 = Iterator.range(0, 10)
+ assertTrue(r1 contains 5)
+ assertTrue(r1 contains 6)
+ assertFalse(r1 contains 4)
+ val r2a = Iterator.range(0, 10, 2)
+ assertFalse(r2a contains 5)
+ val r2b = Iterator.range(0, 10, 2)
+ assertTrue(r2b contains 6)
+ val r3 = Iterator.range(0, 10, 11)
+ assertFalse(r3 contains 5)
+ assertTrue(r3.isEmpty)
+ }
+ @Test def take(): Unit = {
+ assertEquals(10, (Iterator from 0 take 10).size)
+ }
+ @Test def foreach(): Unit = {
+ val it1 = Iterator.from(0) take 20
+ var n = 0
+ it1 foreach { n += _ }
+ assertEquals(190, n)
+ }
+ // ticket #429
+ @Test def fromArray(): Unit = {
+ val a = List(1, 2, 3, 4).toArray
+ var xs0 = a.iterator.toList;
+ var xs1 = a.slice(0, 1).iterator
+ var xs2 = a.slice(0, 2).iterator
+ var xs3 = a.slice(0, 3).iterator
+ var xs4 = a.slice(0, 4).iterator
+ assertEquals(14, xs0.size + xs1.size + xs2.size + xs3.size + xs4.size)
+ }
+ @Test def toSeq(): Unit = {
+ assertEquals("1x2x3x4x5", List(1, 2, 3, 4, 5).iterator.mkString("x"))
+ }
+ @Test def indexOf(): Unit = {
+ assertEquals(3, List(1, 2, 3, 4, 5).iterator.indexOf(4))
+ assertEquals(-1, List(1, 2, 3, 4, 5).iterator.indexOf(16))
+ }
+ @Test def indexWhere(): Unit = {
+ assertEquals(3, List(1, 2, 3, 4, 5).iterator.indexWhere { x: Int => x >= 4 })
+ assertEquals(-1, List(1, 2, 3, 4, 5).iterator.indexWhere { x: Int => x >= 16 })
+ }
+ // iterator-iterate-lazy.scala
+ // was java.lang.UnsupportedOperationException: tail of empty list
+ @Test def iterateIsSufficientlyLazy(): Unit = {
+ //Iterator.iterate((1 to 5).toList)(_.tail).takeWhile(_.nonEmpty).toList // suffices
+ Iterator.iterate((1 to 5).toList)(_.tail).takeWhile(_.nonEmpty).map(_.head).toList
+ }
+ // SI-3516
+ @Test def toStreamIsSufficientlyLazy(): Unit = {
+ val results = collection.mutable.ListBuffer.empty[Int]
+ def mkIterator = (1 to 5).iterator map (x => { results += x ; x })
+ def mkInfinite = Iterator continually { results += 1 ; 1 }
+
+ // Stream is strict in its head so we should see 1 from each of them.
+ val s1 = mkIterator.toStream
+ val s2 = mkInfinite.toStream
+ // back and forth without slipping into nontermination.
+ results += (Stream from 1).toIterator.drop(10).toStream.drop(10).toIterator.next()
+ assertSameElements(List(1,1,21), results)
+ }
}
diff --git a/test/junit/scala/collection/immutable/TreeMapTest.scala b/test/junit/scala/collection/immutable/TreeMapTest.scala
new file mode 100644
index 0000000000..4c21b94b24
--- /dev/null
+++ b/test/junit/scala/collection/immutable/TreeMapTest.scala
@@ -0,0 +1,20 @@
+package scala.collection.immutable
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class TreeMapTest {
+
+ @Test
+ def hasCorrectDropAndTakeMethods() {
+ val tree = TreeMap(1 -> "a", 2 -> "b", 3 -> "c")
+
+ assertEquals(TreeMap.empty[Int, String], tree take Int.MinValue)
+ assertEquals(TreeMap.empty[Int, String], tree takeRight Int.MinValue)
+ assertEquals(tree, tree drop Int.MinValue)
+ assertEquals(tree, tree dropRight Int.MinValue)
+ }
+}
diff --git a/test/junit/scala/collection/immutable/TreeSetTest.scala b/test/junit/scala/collection/immutable/TreeSetTest.scala
new file mode 100644
index 0000000000..8efe1bfeb8
--- /dev/null
+++ b/test/junit/scala/collection/immutable/TreeSetTest.scala
@@ -0,0 +1,20 @@
+package scala.collection.immutable
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class TreeSetTest {
+
+ @Test
+ def hasCorrectDropAndTakeMethods() {
+ val set = TreeSet(1, 2, 3)
+
+ assertEquals(TreeSet.empty[Int], set take Int.MinValue)
+ assertEquals(TreeSet.empty[Int], set takeRight Int.MinValue)
+ assertEquals(set, set drop Int.MinValue)
+ assertEquals(set, set dropRight Int.MinValue)
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
index b892eb36cf..c1c5a71b83 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
@@ -7,6 +7,8 @@ import scala.reflect.io.VirtualDirectory
import scala.tools.asm.Opcodes
import scala.tools.asm.tree.{AbstractInsnNode, LabelNode, ClassNode, MethodNode}
import scala.tools.cmd.CommandLineParser
+import scala.tools.nsc.backend.jvm.opt.LocalOpt
+import scala.tools.nsc.settings.{MutableSettings, ScalaSettings}
import scala.tools.nsc.{Settings, Global}
import scala.tools.partest.ASMConverters
import scala.collection.JavaConverters._
@@ -79,4 +81,23 @@ object CodeGenTools {
def getSingleMethod(classNode: ClassNode, name: String): Method =
convertMethod(classNode.methods.asScala.toList.find(_.name == name).get)
+
+ 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))
+ }
+
+ val localOpt = {
+ val settings = new MutableSettings(msg => throw new IllegalArgumentException(msg))
+ settings.processArguments(List("-Yopt:l:method"), processAll = true)
+ new LocalOpt(settings)
+ }
+
+ import scala.language.implicitConversions
+
+ implicit def aliveInstruction(ins: Instruction): (Instruction, Boolean) = (ins, true)
+
+ implicit class MortalInstruction(val ins: Instruction) extends AnyVal {
+ def dead: (Instruction, Boolean) = (ins, false)
+ }
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
index 2fb5bb8052..89900291ca 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
@@ -10,13 +10,12 @@ import scala.tools.partest.ASMConverters._
@RunWith(classOf[JUnit4])
class DirectCompileTest {
- val compiler = newCompiler(extraArgs = "-Ybackend:GenBCode")
+ val compiler = newCompiler(extraArgs = "-Ybackend:GenBCode -Yopt:l:method")
@Test
def testCompile(): Unit = {
val List(("C.class", bytes)) = compile(compiler)(
- """
- |class C {
+ """class C {
| def f = 1
|}
""".stripMargin)
@@ -26,19 +25,12 @@ class DirectCompileTest {
@Test
def testCompileClasses(): Unit = {
- val List(cClass, cModuleClass) = compileClasses(compiler)(
- """
- |class C
- |object C
- """.stripMargin)
+ val List(cClass, cModuleClass) = compileClasses(compiler)("class C; object C")
assertTrue(cClass.name == "C")
assertTrue(cModuleClass.name == "C$")
- val List(dMirror, dModuleClass) = compileClasses(compiler)(
- """
- |object D
- """.stripMargin)
+ val List(dMirror, dModuleClass) = compileClasses(compiler)("object D")
assertTrue(dMirror.name == "D")
assertTrue(dModuleClass.name == "D$")
@@ -47,35 +39,35 @@ class DirectCompileTest {
@Test
def testCompileMethods(): Unit = {
val List(f, g) = compileMethods(compiler)(
- """
- |def f = 10
+ """def f = 10
|def g = f
""".stripMargin)
assertTrue(f.name == "f")
assertTrue(g.name == "g")
- assertTrue(instructionsFromMethod(f).dropNonOp ===
+ assertSameCode(instructionsFromMethod(f).dropNonOp,
List(IntOp(BIPUSH, 10), Op(IRETURN)))
- assertTrue(instructionsFromMethod(g).dropNonOp ===
- List(VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "C", "f", "()I", false), Op(IRETURN)))
+ assertSameCode(instructionsFromMethod(g).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(compiler)("""def f(x: Int) = if (x == 0) "a" else "b"""")
- assertTrue(instructionsFromMethod(f).dropNonOp === List(
- VarOp(ILOAD, 1),
- Op(ICONST_0),
- Jump(IF_ICMPEQ, Label(6)),
- Jump(GOTO, Label(10)),
- Label(6),
- Ldc(LDC, "a"),
- Jump(GOTO, Label(13)),
- Label(10),
- Ldc(LDC, "b"),
- Label(13),
- Op(ARETURN)
+ assertSameCode(instructionsFromMethod(f).dropLinesFrames, List(
+ Label(0),
+ VarOp(ILOAD, 1),
+ Op(ICONST_0),
+ Jump(IF_ICMPNE,
+ Label(7)),
+ Ldc(LDC, "a"),
+ Op(ARETURN),
+ Label(7),
+ Ldc(LDC, "b"),
+ Op(ARETURN),
+ Label(11)
))
}
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala
new file mode 100644
index 0000000000..fc748196d0
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala
@@ -0,0 +1,80 @@
+package scala.tools.nsc
+package backend.jvm
+package opt
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.tools.asm.Opcodes._
+import org.junit.Assert._
+
+import CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+
+@RunWith(classOf[JUnit4])
+class CompactLocalVariablesTest {
+
+ // 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 = "-target:jvm-1.6 -Ybackend:GenBCode -Yopt:unreachable-code,recurse-unreachable-jumps,compact-locals")
+ val noCompactVarsCompiler = newCompiler(extraArgs = "-target:jvm-1.6 -Ybackend:GenBCode -Yopt:unreachable-code,recurse-unreachable-jumps")
+
+ @Test
+ def compactUnused(): Unit = {
+ val code =
+ """def f: Double = {
+ | try { }
+ | catch {
+ | case _: Throwable =>
+ | // eliminated by dce
+ | val i = 1
+ | val d = 1d
+ | val f = 1f
+ | val l = 1l
+ | }
+ |
+ | val i = 1 // variable index 1 (it's an instance method, so at index 0 we have `this`)
+ | val d = 1d // 2,3
+ | val f = 1f // 4
+ | val l = 1l // 5,6
+ |
+ | try { }
+ | catch {
+ | case _: Throwable =>
+ | // eliminated by dce
+ | val i = 1
+ | val d = 1d
+ | val f = 1f
+ | val l = 1l
+ | }
+ |
+ | val ii = 1 // 7
+ | val dd = 1d // 8,9
+ | val ff = 1f // 10
+ | val ll = 1l // 11,12
+ |
+ | i + ii + d + dd + f + ff + l + ll
+ |}
+ |""".stripMargin
+
+ val List(noCompact) = compileMethods(noCompactVarsCompiler)(code)
+ val List(withCompact) = compileMethods(methodOptCompiler)(code)
+
+ // code is the same, except for local var indices
+ assertTrue(noCompact.instructions.size == withCompact.instructions.size)
+
+ val varOpSlots = convertMethod(withCompact).instructions collect {
+ case VarOp(_, v) => v
+ }
+ assertTrue(varOpSlots.toString, varOpSlots == List(1, 2, 4, 5, 7, 8, 10, 11, // stores
+ 1, 7, 2, 8, 4, 10, 5, 11)) // loads
+
+ // the local variables descriptor table is cleaned up to remove stale entries after dce,
+ // also when the slots are not compacted
+ assertTrue(noCompact.localVariables.size == withCompact.localVariables.size)
+
+ assertTrue(noCompact.maxLocals == 25)
+ assertTrue(withCompact.maxLocals == 13)
+ }
+}
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 57fa1a7b66..7d83c54b5b 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala
@@ -26,7 +26,7 @@ class EmptyExceptionHandlersTest {
Op(RETURN)
)
assertTrue(convertMethod(asmMethod).handlers.length == 1)
- LocalOpt.removeEmptyExceptionHandlers(asmMethod)
+ localOpt.removeEmptyExceptionHandlers(asmMethod)
assertTrue(convertMethod(asmMethod).handlers.isEmpty)
}
@@ -35,12 +35,8 @@ class EmptyExceptionHandlersTest {
val handlers = List(ExceptionHandler(Label(1), Label(2), Label(2), Some(exceptionDescriptor)))
val asmMethod = genMethod(handlers = handlers)(
Label(1), // nops only
- Op(NOP),
- Op(NOP),
Jump(GOTO, Label(3)),
- Op(NOP),
Label(3),
- Op(NOP),
Jump(GOTO, Label(4)),
Label(2), // handler
@@ -51,7 +47,7 @@ class EmptyExceptionHandlersTest {
Op(RETURN)
)
assertTrue(convertMethod(asmMethod).handlers.length == 1)
- LocalOpt.removeEmptyExceptionHandlers(asmMethod)
+ localOpt.removeEmptyExceptionHandlers(asmMethod)
assertTrue(convertMethod(asmMethod).handlers.isEmpty)
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala
new file mode 100644
index 0000000000..8c0168826e
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala
@@ -0,0 +1,99 @@
+package scala.tools.nsc
+package backend.jvm
+package opt
+
+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 CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+
+@RunWith(classOf[JUnit4])
+class EmptyLabelsAndLineNumbersTest {
+ @Test
+ def removeEmptyLineNumbers(): Unit = {
+ val ops = List[(Instruction, Boolean)](
+ Label(1),
+ LineNumber(1, Label(1)),
+ Label(2),
+ Label(3),
+ Op(RETURN),
+
+ Label(4),
+ LineNumber(4, Label(4)).dead,
+ LineNumber(5, Label(4)),
+ Op(RETURN),
+
+ Label(5),
+ LineNumber(6, Label(5)).dead,
+ Label(6),
+ Label(7),
+ LineNumber(7, Label(7)),
+ Op(RETURN),
+
+ Label(9),
+ LineNumber(8, Label(9)).dead,
+ Label(10)
+ )
+
+ val method = genMethod()(ops.map(_._1): _*)
+ assertTrue(localOpt.removeEmptyLineNumbers(method))
+ assertSameCode(instructionsFromMethod(method), ops.filter(_._2).map(_._1))
+ }
+
+ @Test
+ def badlyLocatedLineNumbers(): Unit = {
+ def t(ops: Instruction*) =
+ assertThrows[AssertionError](localOpt.removeEmptyLineNumbers(genMethod()(ops: _*)))
+
+ // line numbers have to be right after their referenced label node
+ t(LineNumber(0, Label(1)), Label(1))
+ t(Label(0), Label(1), LineNumber(0, Label(0)))
+ }
+
+ @Test
+ def removeEmptyLabels(): Unit = {
+ val handler = List(ExceptionHandler(Label(4), Label(5), Label(6), Some("java/lang/Throwable")))
+ def ops(target1: Int, target2: Int, target3: Int, target4: Int, target5: Int, target6: Int) = List[(Instruction, Boolean)](
+ Label(1),
+ Label(2).dead,
+ Label(3).dead,
+ LineNumber(3, Label(target1)),
+ VarOp(ILOAD, 1),
+ Jump(IFGE, Label(target2)),
+
+ Label(4),
+ Label(5).dead,
+ Label(6).dead,
+ VarOp(ILOAD, 2),
+ Jump(IFGE, Label(target3)),
+
+ Label(7),
+ Label(8).dead,
+ Label(9).dead,
+ Op(RETURN),
+
+ LookupSwitch(LOOKUPSWITCH, Label(target4), List(1,2), List(Label(target4), Label(target5))),
+ TableSwitch(TABLESWITCH, 1, 2, Label(target4), List(Label(target4), Label(target5))),
+
+ Label(10),
+ LineNumber(10, Label(10)),
+ Label(11).dead,
+ LineNumber(12, Label(target6))
+ )
+
+ val method = genMethod(handlers = handler)(ops(2, 3, 8, 8, 9, 11).map(_._1): _*)
+ assertTrue(localOpt.removeEmptyLabelNodes(method))
+ val m = convertMethod(method)
+ assertSameCode(m.instructions, ops(1, 1, 7, 7, 7, 10).filter(_._2).map(_._1))
+ assertTrue(m.handlers match {
+ case List(ExceptionHandler(Label(4), Label(4), Label(4), _)) => true
+ case _ => false
+ })
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala
new file mode 100644
index 0000000000..5b0f0f238a
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala
@@ -0,0 +1,83 @@
+package scala.tools.nsc
+package backend.jvm
+package opt
+
+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 CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+
+@RunWith(classOf[JUnit4])
+class MethodLevelOpts {
+ val methodOptCompiler = newCompiler(extraArgs = "-target:jvm-1.6 -Ybackend:GenBCode -Yopt:l:method")
+
+ def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1))
+
+ @Test
+ def eliminateEmptyTry(): Unit = {
+ val code = "def f = { try {} catch { case _: Throwable => 0; () }; 1 }"
+ assertSameCode(singleMethodInstructions(methodOptCompiler)(code), wrapInDefault(Op(ICONST_1), Op(IRETURN)))
+ }
+
+ @Test
+ def cannotEliminateLoadBoxedUnit(): 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)
+ assertTrue(m.handlers.length == 1)
+ assertSameCode(m.instructions.take(3), List(Label(0), LineNumber(1, Label(0)), Field(GETSTATIC, "scala/runtime/BoxedUnit", "UNIT", "Lscala/runtime/BoxedUnit;")))
+ }
+
+ @Test
+ 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)
+ 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))
+ )
+ }
+
+ @Test
+ def inlineReturnInCachtNotTry(): 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)
+ 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)))
+ }
+
+ @Test
+ def simplifyJumpsInTryCatchFinally(): Unit = {
+ val code =
+ """def f: Int =
+ | try {
+ | return 1
+ | } catch {
+ | case _: Throwable =>
+ | return 2
+ | } finally {
+ | return 2
+ | // dead
+ | val x = try 10 catch { case _: Throwable => 11 }
+ | println(x)
+ | }
+ """.stripMargin
+ val m = singleMethod(methodOptCompiler)(code)
+ assertTrue(m.handlers.length == 2)
+ assertSameCode(m.instructions.dropNonOp, // drop line numbers and lables that are only used by line numbers
+
+ // one single label left :-)
+ List(Op(ICONST_1), VarOp(ISTORE, 2), Jump(GOTO, Label(20)), Op(POP), Op(ICONST_2), VarOp(ISTORE, 2), Jump(GOTO, Label(20)), VarOp(ASTORE, 3), Op(ICONST_2), Op(IRETURN), Label(20), Op(ICONST_2), Op(IRETURN))
+ )
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala
new file mode 100644
index 0000000000..360fa1d23d
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala
@@ -0,0 +1,221 @@
+package scala.tools.nsc
+package backend.jvm
+package opt
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.tools.asm.Opcodes._
+import org.junit.Assert._
+
+import CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+
+@RunWith(classOf[JUnit4])
+class SimplifyJumpsTest {
+ @Test
+ def simpleGotoReturn(): Unit = {
+ val ops = List(
+ Jump(GOTO, Label(2)), // replaced by RETURN
+ Op(ICONST_1), // need some code, otherwise removeJumpToSuccessor kicks in
+ Op(POP),
+ Label(1), // multiple labels OK
+ Label(2),
+ Label(3),
+ Op(RETURN)
+ )
+ val method = genMethod()(ops: _*)
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), Op(RETURN) :: ops.tail)
+ }
+
+ @Test
+ def simpleGotoThrow(): Unit = {
+ val rest = List(
+ Op(ICONST_1), // need some code, otherwise removeJumpToSuccessor kicks in
+ Op(POP),
+ Label(1),
+ Label(2),
+ Label(3),
+ Op(ATHROW)
+ )
+ val method = genMethod()(
+ Op(ACONST_NULL) ::
+ Jump(GOTO, Label(2)) :: // replaced by ATHROW
+ rest: _*
+ )
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), Op(ACONST_NULL) :: Op(ATHROW) :: rest)
+ }
+
+ @Test
+ def gotoThrowInTry(): Unit = {
+ val handler = List(ExceptionHandler(Label(1), Label(2), Label(4), Some("java/lang/Throwable")))
+ val initialInstrs = List(
+ Label(1),
+ Op(ACONST_NULL),
+ Jump(GOTO, Label(3)), // not by ATHROW (would move the ATHROW into a try block)
+ Label(2),
+ Op(ICONST_1), // need some code, otherwise removeJumpToSuccessor kicks in
+ Op(POP),
+ Label(3),
+ Op(ATHROW),
+ Label(4),
+ Op(POP),
+ Op(RETURN)
+ )
+ val method = genMethod(handlers = handler)(initialInstrs: _*)
+ assertFalse(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), initialInstrs)
+
+ val optMethod = genMethod()(initialInstrs: _*) // no handler
+ assertTrue(localOpt.simplifyJumps(optMethod))
+ assertSameCode(instructionsFromMethod(optMethod).take(3), List(Label(1), Op(ACONST_NULL), Op(ATHROW)))
+ }
+
+ @Test
+ def simplifyBranchOverGoto(): Unit = {
+ val begin = List(
+ VarOp(ILOAD, 1),
+ Jump(IFGE, Label(2))
+ )
+ val rest = List(
+ Jump(GOTO, Label(3)),
+ Label(11), // other labels here are allowed
+ Label(2),
+ VarOp(ILOAD, 1),
+ Op(RETURN),
+ Label(3),
+ VarOp(ILOAD, 1),
+ Op(IRETURN)
+ )
+ val method = genMethod()(begin ::: rest: _*)
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(
+ instructionsFromMethod(method),
+ List(VarOp(ILOAD, 1), Jump(IFLT, Label(3))) ::: rest.tail )
+
+ // no label allowed between begin and rest. if there's another label, then there could be a
+ // branch that label. eliminating the GOTO would change the behavior.
+ val nonOptMethod = genMethod()(begin ::: Label(22) :: rest: _*)
+ assertFalse(localOpt.simplifyJumps(nonOptMethod))
+ }
+
+ @Test
+ def ensureGotoRemoved(): Unit = {
+ def code(jumps: Instruction*) = List(
+ VarOp(ILOAD, 1)) ::: jumps.toList ::: List(
+ Label(2),
+
+ Op(RETURN),
+ Label(3),
+ Op(RETURN)
+ )
+
+ // ensures that the goto is safely removed. ASM supports removing while iterating, but not the
+ // next element of the current. Here, the current is the IFGE, the next is the GOTO.
+ val method = genMethod()(code(Jump(IFGE, Label(2)), Jump(GOTO, Label(3))): _*)
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), code(Jump(IFLT, Label(3))))
+ }
+
+ @Test
+ def removeJumpToSuccessor(): Unit = {
+ val ops = List(
+ Jump(GOTO, Label(1)),
+ Label(11),
+ Label(1),
+ Label(2),
+ VarOp(ILOAD, 1),
+ Op(IRETURN)
+ )
+ val method = genMethod()(ops: _*)
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), ops.tail)
+ }
+
+ @Test
+ def collapseJumpChains(): Unit = {
+ def ops(target1: Int, target2: Int, target3: Int) = List(
+ VarOp(ILOAD, 1),
+ Jump(IFGE, Label(target1)), // initially 1, then 3
+ VarOp(ILOAD, 1),
+ Op(IRETURN),
+
+ Label(2),
+ Jump(GOTO, Label(target3)),
+
+ Label(1),
+ Jump(GOTO, Label(target2)), // initially 2, then 3
+
+ VarOp(ILOAD, 1), // some code to prevent jumpToSuccessor optimization (once target2 is replaced by 3)
+ Op(RETURN),
+
+ Label(3),
+ VarOp(ILOAD, 1),
+ Op(IRETURN)
+ )
+ val method = genMethod()(ops(1, 2, 3): _*)
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), ops(3, 3, 3))
+ }
+
+ @Test
+ def collapseJumpChainLoop(): Unit = {
+ def ops(target: Int) = List(
+ VarOp(ILOAD, 1),
+ Jump(IFGE, Label(target)),
+
+ Label(4),
+ Jump(GOTO, Label(3)),
+
+ VarOp(ILOAD, 1), // some code to prevent jumpToSuccessor (label 3)
+ Op(IRETURN),
+
+ Label(3),
+ Jump(GOTO, Label(4)),
+
+ Label(2),
+ Jump(GOTO, Label(3))
+ )
+
+ val method = genMethod()(ops(2): _*)
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), ops(3))
+ }
+
+ @Test
+ def simplifyThenElseSameTarget(): Unit = {
+ def ops(jumpOp: Instruction) = List(
+ VarOp(ILOAD, 1),
+ jumpOp,
+ Label(2),
+ Jump(GOTO, Label(1)),
+
+ VarOp(ILOAD, 1), // some code to prevent jumpToSuccessor (label 1)
+ Op(IRETURN),
+
+ Label(1),
+ VarOp(ILOAD, 1),
+ Op(IRETURN)
+ )
+
+ val method = genMethod()(ops(Jump(IFGE, Label(1))): _*)
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), ops(Op(POP)))
+ }
+
+ @Test
+ def thenElseSameTargetLoop(): Unit = {
+ def ops(br: List[Instruction]) = List(
+ VarOp(ILOAD, 1),
+ VarOp(ILOAD, 2)) ::: br ::: List(
+ Label(1),
+ Jump(GOTO, Label(1))
+ )
+ val method = genMethod()(ops(List(Jump(IF_ICMPGE, Label(1)))): _*)
+ assertTrue(localOpt.simplifyJumps(method))
+ assertSameCode(instructionsFromMethod(method), ops(List(Op(POP), Op(POP))))
+ }
+}
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 a3bd7ae6fe..4a45dd9138 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala
@@ -16,12 +16,20 @@ import ASMConverters._
@RunWith(classOf[JUnit4])
class UnreachableCodeTest {
- import UnreachableCodeTest._
+
+ def assertEliminateDead(code: (Instruction, Boolean)*): Unit = {
+ val method = genMethod()(code.map(_._1): _*)
+ localOpt.removeUnreachableCodeImpl(method, "C")
+ val nonEliminated = instructionsFromMethod(method)
+ val expectedLive = code.filter(_._2).map(_._1).toList
+ assertSameCode(nonEliminated, expectedLive)
+ }
// jvm-1.6 enables emitting stack map frames, which impacts the code generation wrt dead basic blocks,
// see comment in BCodeBodyBuilder
- val dceCompiler = newCompiler(extraArgs = "-target:jvm-1.6 -Ybackend:GenBCode -Yopt:unreachable-code")
- val noOptCompiler = newCompiler(extraArgs = "-target:jvm-1.6 -Ybackend:GenBCode -Yopt:l:none")
+ val methodOptCompiler = newCompiler(extraArgs = "-target:jvm-1.6 -Ybackend:GenBCode -Yopt:l:method")
+ val dceCompiler = newCompiler(extraArgs = "-target:jvm-1.6 -Ybackend:GenBCode -Yopt:unreachable-code")
+ val noOptCompiler = newCompiler(extraArgs = "-target:jvm-1.6 -Ybackend:GenBCode -Yopt:l:none")
// jvm-1.5 disables computing stack map frames, and it emits dead code as-is.
val noOptNoFramesCompiler = newCompiler(extraArgs = "-target:jvm-1.5 -Ybackend:GenBCode -Yopt:l:none")
@@ -48,8 +56,8 @@ class UnreachableCodeTest {
@Test
def eliminateNop(): Unit = {
assertEliminateDead(
- // not dead, since visited by data flow analysis. need a different opt to eliminate it.
- Op(NOP),
+ // reachable, but removed anyway.
+ Op(NOP).dead,
Op(RETURN),
Op(NOP).dead
)
@@ -136,28 +144,31 @@ class UnreachableCodeTest {
@Test
def eliminateDeadCatchBlocks(): Unit = {
+ // the Label(1) is live: it's used in the local variable descriptor table (local variable "this" has a range from 0 to 1).
+ 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 } }"
- assertSameCode(singleMethodInstructions(dceCompiler)(code).dropNonOp,
- List(Op(ICONST_0), Op(IRETURN)))
+ val m = singleMethod(dceCompiler)(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 => () }; () }"
- // DCE only removes dead basic blocks, but not NOPs, and also not useless jumps
- assertSameCode(singleMethodInstructions(dceCompiler)(code2).dropNonOp,
- List(Op(NOP), Jump(GOTO, Label(33)), Label(33), Op(RETURN)))
+ // 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)))
val code3 = "def f: Unit = { try { } catch { case _: Exception => try { } catch { case _: Exception => () } }; () }"
- assertSameCode(singleMethodInstructions(dceCompiler)(code3).dropNonOp,
- List(Op(NOP), Jump(GOTO, Label(33)), Label(33), Op(RETURN)))
+ assertSameCode(singleMethodInstructions(methodOptCompiler)(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(dceCompiler)(code4).dropNonOp,
- List(Op(NOP), Jump(GOTO, Label(4)), Label(4), Jump(GOTO, Label(7)), Label(7), Op(RETURN)))
+ assertSameCode(singleMethodInstructions(methodOptCompiler)(code4), wrapInDefault(Op(RETURN)))
}
@Test // test the dce-testing tools
def metaTest(): Unit = {
- assertEliminateDead() // no instructions
-
assertThrows[AssertionError](
assertEliminateDead(Op(RETURN).dead),
_.contains("Expected: List()\nActual : List(Op(RETURN))")
@@ -198,20 +209,3 @@ class UnreachableCodeTest {
List(FrameEntry(F_FULL, List(INTEGER, DOUBLE, Label(1)), List("java/lang/Object", Label(3))), Label(1), Label(3)))
}
}
-
-object UnreachableCodeTest {
- import scala.language.implicitConversions
- implicit def aliveInstruction(ins: Instruction): (Instruction, Boolean) = (ins, true)
-
- implicit class MortalInstruction(val ins: Instruction) extends AnyVal {
- def dead: (Instruction, Boolean) = (ins, false)
- }
-
- def assertEliminateDead(code: (Instruction, Boolean)*): Unit = {
- val cls = wrapInClass(genMethod()(code.map(_._1): _*))
- LocalOpt.removeUnreachableCode(cls)
- val nonEliminated = instructionsFromMethod(cls.methods.get(0))
- val expectedLive = code.filter(_._2).map(_._1).toList
- assertSameCode(nonEliminated, expectedLive)
- }
-}
diff --git a/test/junit/scala/tools/testing/AssertUtil.scala b/test/junit/scala/tools/testing/AssertUtil.scala
index 9b4833d46b..83a637783f 100644
--- a/test/junit/scala/tools/testing/AssertUtil.scala
+++ b/test/junit/scala/tools/testing/AssertUtil.scala
@@ -1,6 +1,11 @@
package scala.tools
package testing
+import org.junit.Assert
+import Assert.fail
+import scala.runtime.ScalaRunTime.stringOf
+import scala.collection.{ GenIterable, IterableLike }
+
/** This module contains additional higher-level assert statements
* that are ultimately based on junit.Assert primitives.
*/
@@ -21,6 +26,19 @@ object AssertUtil {
throw e
else return
}
- throw new AssertionError("Expression did not throw!")
+ fail("Expression did not throw!")
}
+
+ /** JUnit-style assertion for `IterableLike.sameElements`.
+ */
+ def assertSameElements[A, B >: A](expected: IterableLike[A, _], actual: GenIterable[B], message: String = ""): Unit =
+ if (!(expected sameElements actual))
+ fail(
+ f"${ if (message.nonEmpty) s"$message " else "" }expected:<${ stringOf(expected) }> but was:<${ stringOf(actual) }>"
+ )
+
+ /** Convenient for testing iterators.
+ */
+ def assertSameElements[A, B >: A](expected: IterableLike[A, _], actual: Iterator[B]): Unit =
+ assertSameElements(expected, actual.toList, "")
}