summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/files/neg/logImplicits.check2
-rw-r--r--test/files/neg/names-defaults-neg.check6
-rw-r--r--test/files/neg/sammy_disabled.check4
-rw-r--r--test/files/neg/sammy_disabled.flags1
-rw-r--r--test/files/neg/sammy_disabled.scala3
-rw-r--r--test/files/neg/sammy_error.check4
-rw-r--r--test/files/neg/sammy_error.scala7
-rw-r--r--test/files/neg/sammy_error_exist_no_crash.check4
-rw-r--r--test/files/neg/sammy_error_exist_no_crash.flags1
-rw-r--r--test/files/neg/sammy_error_exist_no_crash.scala4
-rw-r--r--test/files/neg/sammy_expected.check6
-rw-r--r--test/files/neg/sammy_expected.scala5
-rw-r--r--test/files/neg/sammy_overload.check7
-rw-r--r--test/files/neg/sammy_overload.scala13
-rw-r--r--test/files/neg/sammy_restrictions.check30
-rw-r--r--test/files/neg/sammy_restrictions.flags1
-rw-r--r--test/files/neg/sammy_restrictions.scala19
-rw-r--r--test/files/neg/sammy_wrong_arity.flags1
-rw-r--r--test/files/neg/t5761.check2
-rw-r--r--test/files/pos/fun_undo_eta.scala10
-rw-r--r--test/files/pos/sammy_ctor_arg.scala4
-rw-r--r--test/files/pos/sammy_exist.flags1
-rw-r--r--test/files/pos/sammy_implicit.scala11
-rw-r--r--test/files/pos/sammy_infer_argtype_subtypes.scala6
-rw-r--r--test/files/pos/sammy_inferargs.scala6
-rw-r--r--test/files/pos/sammy_overload.flags1
-rw-r--r--test/files/pos/sammy_overload.scala27
-rw-r--r--test/files/pos/sammy_override.flags1
-rw-r--r--test/files/pos/sammy_poly.flags1
-rw-r--r--test/files/pos/sammy_poly.scala13
-rw-r--r--test/files/pos/sammy_scope.flags1
-rw-r--r--test/files/pos/sammy_scope.scala4
-rw-r--r--test/files/pos/sammy_single.flags1
-rw-r--r--test/files/pos/sammy_twice.flags1
-rw-r--r--test/files/pos/t4365/a_1.scala2
-rw-r--r--test/files/pos/t4365/b_1.scala2
-rw-r--r--test/files/pos/t8310.flags1
-rw-r--r--test/files/pos/t8429.scala7
-rw-r--r--test/files/pos/t9449.scala19
-rw-r--r--test/files/pos/virtpatmat_exist1.scala3
-rw-r--r--test/files/run/indylambda-boxing/test.scala7
-rw-r--r--test/files/run/lambda-serialization.scala14
-rw-r--r--test/files/run/reflection-mem-typecheck.scala4
-rw-r--r--test/files/run/sammy_after_implicit_view.scala28
-rw-r--r--test/files/run/sammy_cbn.scala9
-rw-r--r--test/files/run/sammy_erasure_cce.scala22
-rw-r--r--test/files/run/sammy_java8.flags1
-rw-r--r--test/files/run/sammy_repeated.flags1
-rw-r--r--test/files/run/sammy_repeated.scala8
-rw-r--r--test/files/run/sammy_restrictions_LMF.check2
-rw-r--r--test/files/run/sammy_restrictions_LMF.scala57
-rw-r--r--test/files/run/sammy_return.scala14
-rw-r--r--test/files/run/sammy_vararg_cbn.check (renamed from test/files/run/sammy_repeated.check)0
-rw-r--r--test/files/run/sammy_vararg_cbn.scala12
-rw-r--r--test/files/run/t8549.scala4
-rw-r--r--test/junit/scala/issues/RunTest.scala143
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala29
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala160
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala7
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala2
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala4
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala4
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala11
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala81
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala6
-rw-r--r--test/junit/scala/util/control/ExceptionTest.scala42
66 files changed, 779 insertions, 135 deletions
diff --git a/test/files/neg/logImplicits.check b/test/files/neg/logImplicits.check
index df7b359767..479bf4ba2c 100644
--- a/test/files/neg/logImplicits.check
+++ b/test/files/neg/logImplicits.check
@@ -4,7 +4,7 @@ logImplicits.scala:2: applied implicit conversion from xs.type to ?{def size: ?}
logImplicits.scala:7: applied implicit conversion from String("abc") to ?{def map: ?} = implicit def augmentString(x: String): scala.collection.immutable.StringOps
def f = "abc" map (_ + 1)
^
-logImplicits.scala:15: inferred view from String("abc") to Int = C.this.convert:(p: String)Int
+logImplicits.scala:15: inferred view from String("abc") to Int via C.this.convert: (p: String)Int
math.max(122, x: Int)
^
logImplicits.scala:19: applied implicit conversion from Int(1) to ?{def ->: ?} = implicit def ArrowAssoc[A](self: A): ArrowAssoc[A]
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index 8a6aafd67a..875bc2ade0 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -130,7 +130,7 @@ names-defaults-neg.scala:102: error: unknown parameter name: m
names-defaults-neg.scala:135: error: reference to var2 is ambiguous; it is both a method parameter and a variable in scope.
delay(var2 = 40)
^
-names-defaults-neg.scala:138: error: missing parameter type for expanded function ((x$1) => a = x$1)
+names-defaults-neg.scala:138: error: missing parameter type for expanded function ((x$1: <error>) => a = x$1)
val taf2: Int => Unit = testAnnFun(a = _, b = get("+"))
^
names-defaults-neg.scala:138: error: not found: value a
@@ -142,10 +142,10 @@ names-defaults-neg.scala:138: error: not found: value get
names-defaults-neg.scala:139: error: parameter 'a' is already specified at parameter position 1
val taf3 = testAnnFun(b = _: String, a = get(8))
^
-names-defaults-neg.scala:140: error: missing parameter type for expanded function ((x$3) => testAnnFun(x$3, ((x$4) => b = x$4)))
+names-defaults-neg.scala:140: error: missing parameter type for expanded function ((x$3: <error>) => testAnnFun(x$3, ((x$4) => b = x$4)))
val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
^
-names-defaults-neg.scala:140: error: missing parameter type for expanded function ((x$4) => b = x$4)
+names-defaults-neg.scala:140: error: missing parameter type for expanded function ((x$4: <error>) => b = x$4)
val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
^
names-defaults-neg.scala:140: error: not found: value b
diff --git a/test/files/neg/sammy_disabled.check b/test/files/neg/sammy_disabled.check
new file mode 100644
index 0000000000..66db9dd5f2
--- /dev/null
+++ b/test/files/neg/sammy_disabled.check
@@ -0,0 +1,4 @@
+sammy_disabled.scala:3: error: missing parameter type
+class C { val f: F = x => "a" }
+ ^
+one error found
diff --git a/test/files/neg/sammy_disabled.flags b/test/files/neg/sammy_disabled.flags
new file mode 100644
index 0000000000..cf42e9f940
--- /dev/null
+++ b/test/files/neg/sammy_disabled.flags
@@ -0,0 +1 @@
+-Xsource:2.11
diff --git a/test/files/neg/sammy_disabled.scala b/test/files/neg/sammy_disabled.scala
new file mode 100644
index 0000000000..12000a3e12
--- /dev/null
+++ b/test/files/neg/sammy_disabled.scala
@@ -0,0 +1,3 @@
+trait F { def apply(x: Int): String }
+
+class C { val f: F = x => "a" }
diff --git a/test/files/neg/sammy_error.check b/test/files/neg/sammy_error.check
new file mode 100644
index 0000000000..f14ac7e3a2
--- /dev/null
+++ b/test/files/neg/sammy_error.check
@@ -0,0 +1,4 @@
+sammy_error.scala:6: error: missing parameter type
+ foo(x => x) // should result in only one error (the second one stemmed from adapting to SAM when the tree was erroneous)
+ ^
+one error found
diff --git a/test/files/neg/sammy_error.scala b/test/files/neg/sammy_error.scala
new file mode 100644
index 0000000000..dbddebf325
--- /dev/null
+++ b/test/files/neg/sammy_error.scala
@@ -0,0 +1,7 @@
+trait F1[A, B] { def apply(a: A): B }
+
+class Test {
+ def foo[A](f1: F1[A, A]) = f1
+
+ foo(x => x) // should result in only one error (the second one stemmed from adapting to SAM when the tree was erroneous)
+}
diff --git a/test/files/neg/sammy_error_exist_no_crash.check b/test/files/neg/sammy_error_exist_no_crash.check
index a0d2237ce0..944b6471fd 100644
--- a/test/files/neg/sammy_error_exist_no_crash.check
+++ b/test/files/neg/sammy_error_exist_no_crash.check
@@ -1,6 +1,4 @@
-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>).
+sammy_error_exist_no_crash.scala:5: error: value parseInt is not a member of String
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
deleted file mode 100644
index e1b37447c9..0000000000
--- a/test/files/neg/sammy_error_exist_no_crash.flags
+++ /dev/null
@@ -1 +0,0 @@
--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
index da7e47206f..667b4db763 100644
--- a/test/files/neg/sammy_error_exist_no_crash.scala
+++ b/test/files/neg/sammy_error_exist_no_crash.scala
@@ -1,6 +1,6 @@
-abstract class F[T] { def apply(s: T): Int }
+trait 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_expected.check b/test/files/neg/sammy_expected.check
new file mode 100644
index 0000000000..3b76aabdd2
--- /dev/null
+++ b/test/files/neg/sammy_expected.check
@@ -0,0 +1,6 @@
+sammy_expected.scala:4: error: type mismatch;
+ found : String => Int
+ required: F[Object,Int]
+ def wrong: F[Object, Int] = (x: String) => 1
+ ^
+one error found
diff --git a/test/files/neg/sammy_expected.scala b/test/files/neg/sammy_expected.scala
new file mode 100644
index 0000000000..8fc1f66ff7
--- /dev/null
+++ b/test/files/neg/sammy_expected.scala
@@ -0,0 +1,5 @@
+trait F[A, B] { def apply(x: A): B }
+
+class MustMeetExpected {
+ def wrong: F[Object, Int] = (x: String) => 1
+} \ No newline at end of file
diff --git a/test/files/neg/sammy_overload.check b/test/files/neg/sammy_overload.check
new file mode 100644
index 0000000000..903d7c88f4
--- /dev/null
+++ b/test/files/neg/sammy_overload.check
@@ -0,0 +1,7 @@
+sammy_overload.scala:11: error: missing parameter type for expanded function ((x$1: <error>) => x$1.toString)
+ O.m(_.toString) // error expected: eta-conversion breaks down due to overloading
+ ^
+sammy_overload.scala:12: error: missing parameter type
+ O.m(x => x) // error expected: needs param type
+ ^
+two errors found
diff --git a/test/files/neg/sammy_overload.scala b/test/files/neg/sammy_overload.scala
new file mode 100644
index 0000000000..91c52cf96c
--- /dev/null
+++ b/test/files/neg/sammy_overload.scala
@@ -0,0 +1,13 @@
+trait ToString { def convert(x: Int): String }
+
+class ExplicitSamType {
+ object O {
+ def m(x: Int => String): Int = 0
+ def m(x: ToString): Int = 1
+ }
+
+ O.m((x: Int) => x.toString) // ok, function type takes precedence
+
+ O.m(_.toString) // error expected: eta-conversion breaks down due to overloading
+ O.m(x => x) // error expected: needs param type
+}
diff --git a/test/files/neg/sammy_restrictions.check b/test/files/neg/sammy_restrictions.check
index 8cc49f9aa9..09579cbe21 100644
--- a/test/files/neg/sammy_restrictions.check
+++ b/test/files/neg/sammy_restrictions.check
@@ -1,26 +1,18 @@
-sammy_restrictions.scala:31: error: type mismatch;
+sammy_restrictions.scala:35: error: type mismatch;
found : () => Int
required: NoAbstract
(() => 0) : NoAbstract
^
-sammy_restrictions.scala:32: error: type mismatch;
+sammy_restrictions.scala:36: error: type mismatch;
found : Int => Int
required: TwoAbstract
((x: Int) => 0): TwoAbstract
^
-sammy_restrictions.scala:34: error: class type required but DerivedOneAbstract with OneAbstract found
- ((x: Int) => 0): NonClassType // "class type required". I think we should avoid SAM translation here.
- ^
-sammy_restrictions.scala:35: error: type mismatch;
+sammy_restrictions.scala:37: error: type mismatch;
found : Int => Int
required: NoEmptyConstructor
((x: Int) => 0): NoEmptyConstructor
^
-sammy_restrictions.scala:37: error: type mismatch;
- found : Int => Int
- required: OneEmptySecondaryConstructor
- ((x: Int) => 0): OneEmptySecondaryConstructor // derived class must have an empty *primary* to call.
- ^
sammy_restrictions.scala:38: error: type mismatch;
found : Int => Int
required: MultipleConstructorLists
@@ -28,22 +20,32 @@ sammy_restrictions.scala:38: error: type mismatch;
^
sammy_restrictions.scala:39: error: type mismatch;
found : Int => Int
+ required: OneEmptySecondaryConstructor
+ ((x: Int) => 0): OneEmptySecondaryConstructor // derived class must have an empty *primary* to call.
+ ^
+sammy_restrictions.scala:40: error: type mismatch;
+ found : Int => Int
required: MultipleMethodLists
((x: Int) => 0): MultipleMethodLists
^
-sammy_restrictions.scala:40: error: type mismatch;
+sammy_restrictions.scala:41: error: type mismatch;
found : Int => Int
required: ImplicitConstructorParam
((x: Int) => 0): ImplicitConstructorParam
^
-sammy_restrictions.scala:41: error: type mismatch;
+sammy_restrictions.scala:42: error: type mismatch;
found : Int => Int
required: ImplicitMethodParam
((x: Int) => 0): ImplicitMethodParam
^
-sammy_restrictions.scala:44: error: type mismatch;
+sammy_restrictions.scala:43: error: type mismatch;
found : Int => Int
required: PolyMethod
((x: Int) => 0): PolyMethod
^
+sammy_restrictions.scala:44: error: type mismatch;
+ found : Int => Int
+ required: SelfTp
+ ((x: Int) => 0): SelfTp
+ ^
10 errors found
diff --git a/test/files/neg/sammy_restrictions.flags b/test/files/neg/sammy_restrictions.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/neg/sammy_restrictions.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/neg/sammy_restrictions.scala b/test/files/neg/sammy_restrictions.scala
index d003cfaf36..ff2c16b679 100644
--- a/test/files/neg/sammy_restrictions.scala
+++ b/test/files/neg/sammy_restrictions.scala
@@ -24,22 +24,29 @@ abstract class PolyMethod { def ap[T](a: T): T }
abstract class OneAbstract { def ap(a: Int): Any }
abstract class DerivedOneAbstract extends OneAbstract
+abstract class SelfTp { self: NoAbstract => def ap(a: Int): Any }
+abstract class SelfVar { self => def ap(a: Int): Any }
+
object Test {
implicit val s: String = ""
type NonClassType = DerivedOneAbstract with OneAbstract
+ // errors:
(() => 0) : NoAbstract
((x: Int) => 0): TwoAbstract
- ((x: Int) => 0): DerivedOneAbstract // okay
- ((x: Int) => 0): NonClassType // "class type required". I think we should avoid SAM translation here.
((x: Int) => 0): NoEmptyConstructor
- ((x: Int) => 0): OneEmptyConstructor // okay
- ((x: Int) => 0): OneEmptySecondaryConstructor // derived class must have an empty *primary* to call.
((x: Int) => 0): MultipleConstructorLists
+ ((x: Int) => 0): OneEmptySecondaryConstructor // derived class must have an empty *primary* to call.
((x: Int) => 0): MultipleMethodLists
((x: Int) => 0): ImplicitConstructorParam
((x: Int) => 0): ImplicitMethodParam
-
- ((x: Int) => 0): PolyClass[Int] // okay
((x: Int) => 0): PolyMethod
+ ((x: Int) => 0): SelfTp
+
+ // allowed:
+ ((x: Int) => 0): OneEmptyConstructor
+ ((x: Int) => 0): DerivedOneAbstract
+ ((x: Int) => 0): NonClassType // we also allow type aliases in instantiation expressions, if they resolve to a class type
+ ((x: Int) => 0): PolyClass[Int]
+ ((x: Int) => 0): SelfVar
}
diff --git a/test/files/neg/sammy_wrong_arity.flags b/test/files/neg/sammy_wrong_arity.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/neg/sammy_wrong_arity.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/neg/t5761.check b/test/files/neg/t5761.check
index 2d66af26f6..15c0bc7634 100644
--- a/test/files/neg/t5761.check
+++ b/test/files/neg/t5761.check
@@ -13,7 +13,7 @@ Unspecified value parameter x.
t5761.scala:13: error: not found: type Tread
new Tread("sth") { }.run()
^
-t5761.scala:13: error: value run is not a member of AnyRef
+t5761.scala:13: error: value run is not a member of <error>
new Tread("sth") { }.run()
^
5 errors found
diff --git a/test/files/pos/fun_undo_eta.scala b/test/files/pos/fun_undo_eta.scala
new file mode 100644
index 0000000000..466b0e2629
--- /dev/null
+++ b/test/files/pos/fun_undo_eta.scala
@@ -0,0 +1,10 @@
+class Test {
+ def m(i: Int) = i
+
+ def expectWild[A](f: A) = ???
+ def expectFun[A](f: A => Int) = ???
+
+ expectWild((i => m(i))) // manual eta expansion
+ expectWild(m(_)) // have to undo eta expansion with wildcard expected type
+ expectFun(m(_)) // have to undo eta expansion with function expected type
+}
diff --git a/test/files/pos/sammy_ctor_arg.scala b/test/files/pos/sammy_ctor_arg.scala
new file mode 100644
index 0000000000..3c556d59f0
--- /dev/null
+++ b/test/files/pos/sammy_ctor_arg.scala
@@ -0,0 +1,4 @@
+trait Fun[A, B] { def apply(a: A): B }
+// can't do sam expansion until the sam body def is a static method in the sam class, and not a local method in a block'
+class C(f: Fun[Int, String])
+class Test extends C(s => "a") \ No newline at end of file
diff --git a/test/files/pos/sammy_exist.flags b/test/files/pos/sammy_exist.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/pos/sammy_exist.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/pos/sammy_implicit.scala b/test/files/pos/sammy_implicit.scala
new file mode 100644
index 0000000000..ab63fc729e
--- /dev/null
+++ b/test/files/pos/sammy_implicit.scala
@@ -0,0 +1,11 @@
+trait Fun[A, B] { def apply(a: A): B }
+
+abstract class SamImplicitConvert {
+ class Lst[T]
+ abstract class Str { def getBytes: Array[Int] }
+ def flatMap[B](f: Fun[Str, Lst[B]]): List[B] = ???
+
+ implicit def conv(xs: Array[Int]): Lst[Int]
+
+ def encoded = flatMap (_.getBytes)
+}
diff --git a/test/files/pos/sammy_infer_argtype_subtypes.scala b/test/files/pos/sammy_infer_argtype_subtypes.scala
new file mode 100644
index 0000000000..63966f879e
--- /dev/null
+++ b/test/files/pos/sammy_infer_argtype_subtypes.scala
@@ -0,0 +1,6 @@
+trait Fun[A, B] { def apply(a: A): B }
+
+class SamInferResult {
+ def foreach[U](f: Fun[String, U]): U = ???
+ def foo = foreach(println)
+} \ No newline at end of file
diff --git a/test/files/pos/sammy_inferargs.scala b/test/files/pos/sammy_inferargs.scala
new file mode 100644
index 0000000000..10d9b4f0dd
--- /dev/null
+++ b/test/files/pos/sammy_inferargs.scala
@@ -0,0 +1,6 @@
+trait Proc { def apply(): Unit }
+class Test {
+ val initCode = List[Proc]()
+ initCode foreach { proc => proc() }
+
+}
diff --git a/test/files/pos/sammy_overload.flags b/test/files/pos/sammy_overload.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/pos/sammy_overload.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/pos/sammy_overload.scala b/test/files/pos/sammy_overload.scala
index 5472248f4d..6a3c88ec55 100644
--- a/test/files/pos/sammy_overload.scala
+++ b/test/files/pos/sammy_overload.scala
@@ -6,4 +6,29 @@ object Test {
def foo(x: String): Unit = ???
def foo(): Unit = ???
val f: Consumer[_ >: String] = foo
-} \ No newline at end of file
+}
+
+trait A[A, B] { def apply(a: A): B }
+
+class ArityDisambiguate {
+ object O {
+ def m(a: A[Int, Int]) = 0
+ def m(f: (Int, Int) => Int) = 1
+ }
+
+ O.m(x => x) // ok
+ O.m((x, y) => x) // ok
+}
+
+class InteractionWithImplicits {
+ object O {
+ class Ev
+ implicit object E1 extends Ev
+ implicit object E2 extends Ev
+ def m(a: A[Int, Int])(implicit ol: E1.type) = 0
+ def m(a: A[String, Int])(implicit ol: E2.type) = 1
+ }
+
+ O.m((x: Int) => 1) // ok
+ O.m((x: String) => 1) // ok
+}
diff --git a/test/files/pos/sammy_override.flags b/test/files/pos/sammy_override.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/pos/sammy_override.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/pos/sammy_poly.flags b/test/files/pos/sammy_poly.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/pos/sammy_poly.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/pos/sammy_poly.scala b/test/files/pos/sammy_poly.scala
index c629be7166..ba10baea49 100644
--- a/test/files/pos/sammy_poly.scala
+++ b/test/files/pos/sammy_poly.scala
@@ -1,7 +1,12 @@
// test synthesizeSAMFunction where the sam type is not fully defined
-class T {
- trait F[T, U] { def apply(x: T): U }
- // NOTE: the f(x) desugaring for now assumes the single abstract method is called 'apply'
+trait F[T, R]{ def apply(x: T): R }
+
+class PolySammy {
+ (x => x + 1): F[Int, Int]
+ ((x: Int) => x + 1): F[Int, Int]
+ ((x: String) => 1): F[String, Int]
+ ((x: Object) => 1): F[String, Int]
+
def app[T, U](x: T)(f: F[T, U]): U = f(x)
app(1)(x => List(x))
-} \ No newline at end of file
+}
diff --git a/test/files/pos/sammy_scope.flags b/test/files/pos/sammy_scope.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/pos/sammy_scope.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/pos/sammy_scope.scala b/test/files/pos/sammy_scope.scala
index 8f1fe7058e..9d35501a47 100644
--- a/test/files/pos/sammy_scope.scala
+++ b/test/files/pos/sammy_scope.scala
@@ -1,8 +1,8 @@
// test synthesizeSAMFunction: scope hygiene
-abstract class SamFun[T1, R] { self =>
+trait SamFun[T1, R] { self =>
def apply(v1: T1): R
// this should type check, as the apply ref is equivalent to self.apply
// it shouldn't resolve to the sam's apply that's synthesized (that wouldn't type check, hence the pos test)
def compose[A](g: SamFun[A, T1]): SamFun[A, R] = { x => apply(g(x)) }
-} \ No newline at end of file
+}
diff --git a/test/files/pos/sammy_single.flags b/test/files/pos/sammy_single.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/pos/sammy_single.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/pos/sammy_twice.flags b/test/files/pos/sammy_twice.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/pos/sammy_twice.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/pos/t4365/a_1.scala b/test/files/pos/t4365/a_1.scala
index a24b57772d..e7466e0d48 100644
--- a/test/files/pos/t4365/a_1.scala
+++ b/test/files/pos/t4365/a_1.scala
@@ -9,7 +9,7 @@ trait SeqViewLike[+A,
trait Transformed[+B] extends super[GenSeqViewLike].Transformed[B]
abstract class AbstractTransformed[+B] extends Seq[B] with Transformed[B] {
- def underlying: Coll = error("")
+ def underlying: Coll = sys.error("")
}
trait Reversed extends Transformed[A] with super[GenSeqViewLike].Reversed
diff --git a/test/files/pos/t4365/b_1.scala b/test/files/pos/t4365/b_1.scala
index e1423813f1..1158db6c32 100644
--- a/test/files/pos/t4365/b_1.scala
+++ b/test/files/pos/t4365/b_1.scala
@@ -10,7 +10,7 @@ self =>
trait Transformed[+B] {
def length: Int = 0
- def apply(idx: Int): B = error("")
+ def apply(idx: Int): B = sys.error("")
}
trait Reversed extends Transformed[A] {
diff --git a/test/files/pos/t8310.flags b/test/files/pos/t8310.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/pos/t8310.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/pos/t8429.scala b/test/files/pos/t8429.scala
new file mode 100644
index 0000000000..a2d32637e1
--- /dev/null
+++ b/test/files/pos/t8429.scala
@@ -0,0 +1,7 @@
+trait Must { def musta(str: String, i: Int): Unit }
+
+object Mustare {
+ def takesM(m: Must) = ???
+ takesM{ (a, b) => println } // ok
+ takesM{ case (a: String, b: Int) => println("") } // should also be accepted
+}
diff --git a/test/files/pos/t9449.scala b/test/files/pos/t9449.scala
new file mode 100644
index 0000000000..3b86dc80a0
--- /dev/null
+++ b/test/files/pos/t9449.scala
@@ -0,0 +1,19 @@
+trait II {
+ def apply(x: Int): Int
+}
+
+object Test {
+ def ii(x: Int): Int = x
+ def test = {
+ val ii1: II = x => ii(x) // works
+ val ii2: II = ii // works (adapting `ii` to `II`)
+ val ii3: II = ii _ // works (failed before the fix)
+ // typedTyped({ii : (() => <empty>)})
+ // typedEta(ii, pt = II)
+ // adapt(ii, pt = (? => ?))
+ // instantiatedToMethodType(ii, pt = (? => ?))
+ // val ii3: II = ii _ // error:
+ // found : Int => Int
+ // required: II
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/virtpatmat_exist1.scala b/test/files/pos/virtpatmat_exist1.scala
index 6cad017b0b..1f24892489 100644
--- a/test/files/pos/virtpatmat_exist1.scala
+++ b/test/files/pos/virtpatmat_exist1.scala
@@ -1,5 +1,6 @@
import annotation.unchecked.{ uncheckedVariance=> uV }
-import scala.collection.immutable.{ListMap, HashMap, ListSet, HashSet}
+import scala.collection.immutable.{ListMap, ListSet}
+import scala.collection.mutable.{HashMap, HashSet}
object Test {
class HashMapCollision1[A, +B](var hash: Int, var kvs: ListMap[A, B @uV]) extends HashMap[A, B @uV]
diff --git a/test/files/run/indylambda-boxing/test.scala b/test/files/run/indylambda-boxing/test.scala
index cc0a460640..82f8d2f497 100644
--- a/test/files/run/indylambda-boxing/test.scala
+++ b/test/files/run/indylambda-boxing/test.scala
@@ -2,15 +2,16 @@ class Capture
class Test {
def test1 = (i: Int) => ""
def test2 = (i: VC) => i
- def test3 = (i: Int) => i
+ def test3 = (i: Int) => i // not adapted, specialized
- def test4 = {val c = new Capture; (i: Int) => {(c, Test.this.toString); 42} }
+ def test4 = {val c = new Capture; (i: Int) => {(c, Test.this.toString); 42} } // not adapted, specialized
def test5 = {val c = new Capture; (i: VC) => (c, Test.this.toString) }
def test6 = {val c = new Capture; (i: Int) => (c, Test.this.toString) }
def test7 = {val vc = new Capture; (i: Int) => vc }
- def test8 = {val c = 42; (s: String) => (s, c)}
+ def test8 = {val c = 42; (s: String) => (s, c)} // not adapted
def test9 = {val c = 42; (s: String) => ()}
+ def test10 = {(s: List[String]) => ()}
}
object Test {
diff --git a/test/files/run/lambda-serialization.scala b/test/files/run/lambda-serialization.scala
index 46b26d7c5e..0eee1193d7 100644
--- a/test/files/run/lambda-serialization.scala
+++ b/test/files/run/lambda-serialization.scala
@@ -1,8 +1,11 @@
import java.io.{ByteArrayInputStream, ObjectInputStream, ObjectOutputStream, ByteArrayOutputStream}
+trait IntToString { def apply(i: Int): String }
+
object Test {
def main(args: Array[String]): Unit = {
- roundTrip
+ roundTrip()
+ roundTripIndySam()
}
def roundTrip(): Unit = {
@@ -22,6 +25,15 @@ object Test {
assert(serializeDeserialize(serializeDeserialize(specializedLambda)).apply(42) == 2)
}
+ // lambda targeting a SAM, not a FunctionN (should behave the same way)
+ def roundTripIndySam(): Unit = {
+ val lambda: IntToString = (x: Int) => "yo!" * x
+ val reconstituted1 = serializeDeserialize(lambda).asInstanceOf[IntToString]
+ val reconstituted2 = serializeDeserialize(reconstituted1).asInstanceOf[IntToString]
+ assert(reconstituted1.apply(2) == "yo!yo!")
+ assert(reconstituted1.getClass == reconstituted2.getClass)
+ }
+
def serializeDeserialize[T <: AnyRef](obj: T) = {
val buffer = new ByteArrayOutputStream
val out = new ObjectOutputStream(buffer)
diff --git a/test/files/run/reflection-mem-typecheck.scala b/test/files/run/reflection-mem-typecheck.scala
index e3cabf689d..93ec1c937a 100644
--- a/test/files/run/reflection-mem-typecheck.scala
+++ b/test/files/run/reflection-mem-typecheck.scala
@@ -11,7 +11,9 @@ object Test extends MemoryTest {
cm.mkToolBox()
}
- override def maxDelta = 10
+ // I'm not sure this is a great way to test for memory leaks,
+ // since we're also testing how good the JVM's GC is, and this is not easily reproduced between machines/over time
+ override def maxDelta = 12
override def calcsPerIter = 8
override def calc() {
var snippet = """
diff --git a/test/files/run/sammy_after_implicit_view.scala b/test/files/run/sammy_after_implicit_view.scala
new file mode 100644
index 0000000000..a13a71e562
--- /dev/null
+++ b/test/files/run/sammy_after_implicit_view.scala
@@ -0,0 +1,28 @@
+trait MySam { def apply(x: Int): String }
+
+// check that SAM conversion happens after implicit view application
+object Test extends App {
+ final val AnonFunClass = "$anon$"
+ final val LMFClass = "$$Lambda$" // LambdaMetaFactory names classes like this
+
+ // if there's an implicit conversion, it does not takes precedence (because that's what dotty does)
+ def implicitSam() = {
+ import language.implicitConversions
+ var ok = true
+ implicit def fun2sam(fun: Int => String): MySam = { ok = false; new MySam { def apply(x: Int) = fun(x) } }
+ val className = (((x: Int) => x.toString): MySam).getClass.toString
+ assert(ok, "implicit conversion not called")
+ assert(!(className contains AnonFunClass), className)
+ assert(className contains LMFClass, className)
+ }
+
+ // indirectly check that this sam type instance was created from a class spun up by LambdaMetaFactory
+ def justSammy() = {
+ val className = (((x: Int) => x.toString): MySam).getClass.toString
+ assert(!(className contains AnonFunClass), className)
+ assert(className contains LMFClass, className)
+ }
+
+ implicitSam()
+ justSammy()
+}
diff --git a/test/files/run/sammy_cbn.scala b/test/files/run/sammy_cbn.scala
new file mode 100644
index 0000000000..b84b2fd8e5
--- /dev/null
+++ b/test/files/run/sammy_cbn.scala
@@ -0,0 +1,9 @@
+trait F0[T] { def apply(): T }
+
+object Test extends App {
+ def delay[T](v: => T) = (v _): F0[T]
+
+ // should not fail with ClassCastException: $$Lambda$6279/897871870 cannot be cast to F0
+ // (also, should not say boe!)
+ delay(println("boe!"))
+}
diff --git a/test/files/run/sammy_erasure_cce.scala b/test/files/run/sammy_erasure_cce.scala
new file mode 100644
index 0000000000..fb973befe4
--- /dev/null
+++ b/test/files/run/sammy_erasure_cce.scala
@@ -0,0 +1,22 @@
+trait F1 {
+ def apply(a: List[String]): String
+ def f1 = "f1"
+}
+
+object Test extends App {
+ // Wrap the sam-targeting function in a context where the expected type is erased (identity's argument type erases to Object),
+ // so that Erasure can't tell that the types actually conform by looking only
+ // at an un-adorned Function tree and the expected type
+ // (because a function type needs no cast it the expected type is a SAM type),
+ //
+ // A correct implementation of Typers/Erasure tracks a Function's SAM target type directly
+ // (currently using an attachment for backwards compat),
+ // and not in the expected type (which was the case in my first attempt),
+ // as the expected type may lose its SAM status due to erasure.
+ // (In a sense, this need not be so, but erasure drops type parameters,
+ // so that identity's F1 type argument cannot be propagated to its argument type.)
+ def foo = identity[F1]((as: List[String]) => as.head)
+
+ // check that this doesn't CCE's
+ foo.f1
+}
diff --git a/test/files/run/sammy_java8.flags b/test/files/run/sammy_java8.flags
deleted file mode 100644
index 48fd867160..0000000000
--- a/test/files/run/sammy_java8.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental
diff --git a/test/files/run/sammy_repeated.flags b/test/files/run/sammy_repeated.flags
deleted file mode 100644
index e1b37447c9..0000000000
--- a/test/files/run/sammy_repeated.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xexperimental \ No newline at end of file
diff --git a/test/files/run/sammy_repeated.scala b/test/files/run/sammy_repeated.scala
deleted file mode 100644
index c24dc41909..0000000000
--- a/test/files/run/sammy_repeated.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-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/sammy_restrictions_LMF.check b/test/files/run/sammy_restrictions_LMF.check
new file mode 100644
index 0000000000..6ed281c757
--- /dev/null
+++ b/test/files/run/sammy_restrictions_LMF.check
@@ -0,0 +1,2 @@
+1
+1
diff --git a/test/files/run/sammy_restrictions_LMF.scala b/test/files/run/sammy_restrictions_LMF.scala
new file mode 100644
index 0000000000..aa49e14113
--- /dev/null
+++ b/test/files/run/sammy_restrictions_LMF.scala
@@ -0,0 +1,57 @@
+trait T[@specialized A] { def apply(a: A): A }
+trait TInt extends T[Int]
+
+trait TWithVal { val x: Any = 1; def apply(x: Int): String }
+
+trait TImpure { def apply(x: Int): String ; println(1) }
+
+trait Println { println(1) }
+trait TImpureSuper extends Println { def apply(x: Int): String }
+
+class C
+trait A extends C
+trait B extends A
+trait TClassParent extends B { def apply(x: Int): String }
+
+object Test extends App {
+ final val AnonFunClass = "$anonfun$"
+ final val LMFClass = "$$Lambda$" // LambdaMetaFactory names classes like this
+
+ private def LMF(f: Any): Unit = {
+ val className = f.getClass.toString
+ assert(!(className contains AnonFunClass), className)
+ assert((className contains LMFClass), className)
+ }
+
+ private def notLMF(f: Any): Unit = {
+ val className = f.getClass.toString
+ assert((className contains AnonFunClass), className)
+ assert(!(className contains LMFClass), className)
+ }
+
+ // Check that we expand the SAM of a type that is specialized.
+ // This is an implementation restriction -- the current specialization scheme is not
+ // amenable to using LambdaMetaFactory to spin up subclasses.
+ // Since the generic method is abstract, and the specialized ones are concrete,
+ // specialization is rendered moot because we cannot implement the specialized method
+ // with the lambda using LMF.
+
+ // not LMF if specialized at this type
+ notLMF((x => x): T[Int])
+ // not LMF if specialized at this type (via subclass)
+ notLMF((x => x): TInt)
+ // LMF ok if not specialized at this type
+ LMF((x => x): T[String])
+
+ // traits with a val member also cannot be instantiated by LMF
+ val fVal: TWithVal = (x => "a")
+ notLMF(fVal)
+ assert(fVal.x == 1)
+
+ notLMF((x => "a"): TImpure)
+ notLMF((x => "a"): TImpureSuper)
+
+ val fClassParent: TClassParent = x => "a"
+ notLMF(fClassParent)
+ assert(fClassParent(1) == "a")
+}
diff --git a/test/files/run/sammy_return.scala b/test/files/run/sammy_return.scala
new file mode 100644
index 0000000000..e959619dd1
--- /dev/null
+++ b/test/files/run/sammy_return.scala
@@ -0,0 +1,14 @@
+trait Fun[A, B] { def apply(a: A): B }
+class PF[A, B] { def runWith[U](action: Fun[B, U]): Fun[A, Boolean] = a => {action(a.asInstanceOf[B]); true} }
+
+class TO[A](x: A) {
+ def foreach[U](f: Fun[A, U]): U = f(x)
+ def collectFirst[B](pf: PF[A, B]): Option[B] = {
+ foreach(pf.runWith(b => return Some(b)))
+ None
+ }
+}
+
+object Test extends App {
+ assert(new TO("a").collectFirst(new PF[String, String]).get == "a")
+} \ No newline at end of file
diff --git a/test/files/run/sammy_repeated.check b/test/files/run/sammy_vararg_cbn.check
index 1cff0f067c..1cff0f067c 100644
--- a/test/files/run/sammy_repeated.check
+++ b/test/files/run/sammy_vararg_cbn.check
diff --git a/test/files/run/sammy_vararg_cbn.scala b/test/files/run/sammy_vararg_cbn.scala
new file mode 100644
index 0000000000..e5b49498ea
--- /dev/null
+++ b/test/files/run/sammy_vararg_cbn.scala
@@ -0,0 +1,12 @@
+trait SamRepeated { def accept(a: Any*): Unit }
+trait SamByName { def accept(a: => Any): (Any, Any) }
+
+object Test extends App {
+ val rep: SamRepeated = (a) => println(a)
+ rep.accept(1)
+
+ val nam: SamByName = (a) => (a, a)
+ var v = 0
+ assert(nam.accept({v += 1; v}) == (1, 2))
+ assert(v == 2, "by name arg should be evaluated twice")
+}
diff --git a/test/files/run/t8549.scala b/test/files/run/t8549.scala
index 233a05dee1..e2d0d335b0 100644
--- a/test/files/run/t8549.scala
+++ b/test/files/run/t8549.scala
@@ -79,7 +79,7 @@ object Test extends App {
}
}
- // Generated on 20150925-14:41:27 with Scala version 2.12.0-20150924-125956-fd5994f397)
+ // Generated on 20160328-17:47:35 with Scala version 2.12.0-20160328-174205-d46145c)
overwrite.foreach(updateComment)
check(Some(1))("rO0ABXNyAApzY2FsYS5Tb21lESLyaV6hi3QCAAFMAAF4dAASTGphdmEvbGFuZy9PYmplY3Q7eHIADHNjYWxhLk9wdGlvbv5pN/3bDmZ0AgAAeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAQ==")
@@ -176,7 +176,7 @@ object Test extends App {
// check(mutable.ArrayBuffer(1, 2, 3))( "rO0ABXNyACRzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlCdWZmZXIVOLBTg4KOcwIAA0kAC2luaXRpYWxTaXplSQAFc2l6ZTBbAAVhcnJheXQAE1tMamF2YS9sYW5nL09iamVjdDt4cAAAABAAAAADdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAEHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgAFAAAAAnNxAH4ABQAAAANwcHBwcHBwcHBwcHBw")
// TODO SI-8576 Uninitialized field under -Xcheckinit
// check(mutable.ArraySeq(1, 2, 3))( "rO0ABXNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlTZXEVPD3SKEkOcwIAAkkABmxlbmd0aFsABWFycmF5dAATW0xqYXZhL2xhbmcvT2JqZWN0O3hwAAAAA3VyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ABQAAAAJzcQB+AAUAAAAD")
- check(mutable.AnyRefMap("a" -> "A"))( "rO0ABXNyACJzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQW55UmVmTWFwAAAAAAAAAAECAAdJAAVfc2l6ZUkAB192YWNhbnRJAARtYXNrTAAMZGVmYXVsdEVudHJ5dAARTHNjYWxhL0Z1bmN0aW9uMTtbACtzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkQW55UmVmTWFwJCRfaGFzaGVzdAACW0lbAClzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkQW55UmVmTWFwJCRfa2V5c3QAE1tMamF2YS9sYW5nL09iamVjdDtbACtzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkQW55UmVmTWFwJCRfdmFsdWVzcQB+AAN4cAAAAAEAAAAAAAAAB3NyACFqYXZhLmxhbmcuaW52b2tlLlNlcmlhbGl6ZWRMYW1iZGFvYdCULCk2hQIACkkADmltcGxNZXRob2RLaW5kWwAMY2FwdHVyZWRBcmdzcQB+AANMAA5jYXB0dXJpbmdDbGFzc3QAEUxqYXZhL2xhbmcvQ2xhc3M7TAAYZnVuY3Rpb25hbEludGVyZmFjZUNsYXNzdAASTGphdmEvbGFuZy9TdHJpbmc7TAAdZnVuY3Rpb25hbEludGVyZmFjZU1ldGhvZE5hbWVxAH4AB0wAImZ1bmN0aW9uYWxJbnRlcmZhY2VNZXRob2RTaWduYXR1cmVxAH4AB0wACWltcGxDbGFzc3EAfgAHTAAOaW1wbE1ldGhvZE5hbWVxAH4AB0wAE2ltcGxNZXRob2RTaWduYXR1cmVxAH4AB0wAFmluc3RhbnRpYXRlZE1ldGhvZFR5cGVxAH4AB3hwAAAABnVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAB2cgAjc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkFueVJlZk1hcCTiaIeloJGDLgIABUkACUluZGV4TWFza0kACk1pc3NWYWNhbnRJAApNaXNzaW5nQml0SQAJVmFjYW50Qml0TAA0c2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFueVJlZk1hcCQkZXhjZXB0aW9uRGVmYXVsdHEAfgABeHB0AB5zY2FsYS9ydW50aW1lL2phdmE4L0pGdW5jdGlvbjF0AAVhcHBseXQAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7dAAjc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL0FueVJlZk1hcCR0AC5zY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkQW55UmVmTWFwJCQkYW5vbmZ1biQydAAsKExqYXZhL2xhbmcvT2JqZWN0OylMc2NhbGEvcnVudGltZS9Ob3RoaW5nJDtxAH4AEnVyAAJbSU26YCZ26rKlAgAAeHAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPlJANgAAAAB1cQB+AAkAAAAIcHBwcHBwdAABYXB1cQB+AAkAAAAIcHBwcHBwdAABQXA=")
+ check(mutable.AnyRefMap("a" -> "A"))( "rO0ABXNyACJzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQW55UmVmTWFwAAAAAAAAAAECAAdJAAVfc2l6ZUkAB192YWNhbnRJAARtYXNrTAAMZGVmYXVsdEVudHJ5dAARTHNjYWxhL0Z1bmN0aW9uMTtbACtzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkQW55UmVmTWFwJCRfaGFzaGVzdAACW0lbAClzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkQW55UmVmTWFwJCRfa2V5c3QAE1tMamF2YS9sYW5nL09iamVjdDtbACtzY2FsYSRjb2xsZWN0aW9uJG11dGFibGUkQW55UmVmTWFwJCRfdmFsdWVzcQB+AAN4cAAAAAEAAAAAAAAAB3NyADNzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQW55UmVmTWFwJEV4Y2VwdGlvbkRlZmF1bHQAAAAAAAAAAQIAAHhwdXIAAltJTbpgJnbqsqUCAAB4cAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+UkA2AAAAAHVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAhwcHBwcHB0AAFhcHVxAH4ACQAAAAhwcHBwcHB0AAFBcA==")
check(mutable.ArrayStack(1, 2, 3))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlTdGFja3bdxXbcnLBeAgACSQAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFycmF5U3RhY2skJGluZGV4WwAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFycmF5U3RhY2skJHRhYmxldAATW0xqYXZhL2xhbmcvT2JqZWN0O3hwAAAAA3VyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAA3NxAH4ABQAAAAJzcQB+AAUAAAAB")
check(mutable.DoubleLinkedList(1, 2, 3))( "rO0ABXNyAClzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuRG91YmxlTGlua2VkTGlzdI73LKsKRr1RAgADTAAEZWxlbXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wABG5leHR0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1NlcTtMAARwcmV2cQB+AAJ4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgAAc3EAfgAEAAAAAnNxAH4AAHNxAH4ABAAAAANzcQB+AABwcQB+AAtxAH4ACXEAfgAHcQB+AANw")
diff --git a/test/junit/scala/issues/RunTest.scala b/test/junit/scala/issues/RunTest.scala
new file mode 100644
index 0000000000..2bc8008222
--- /dev/null
+++ b/test/junit/scala/issues/RunTest.scala
@@ -0,0 +1,143 @@
+package scala.issues
+
+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
+
+object RunTest extends ClearAfterClass.Clearable {
+ var toolBox = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
+ override def clear(): Unit = { toolBox = null }
+
+ // definitions for individual tests
+
+ class VC(val x: Any) extends AnyVal
+}
+
+@RunWith(classOf[JUnit4])
+class RunTest extends ClearAfterClass {
+ ClearAfterClass.stateToClear = RunTest
+
+ def run[T](code: String): T = {
+ val tb = RunTest.toolBox
+ tb.eval(tb.parse(code)).asInstanceOf[T]
+ }
+
+ @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))
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala b/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala
index 758566fe53..d29f6b0a13 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/IndyLambdaTest.scala
@@ -31,25 +31,44 @@ class IndyLambdaTest extends ClearAfterClass {
case _ => Nil
}.head
}
+
+ val obj = "Ljava/lang/Object;"
+ val str = "Ljava/lang/String;"
+
// unspecialized functions that have a primitive in parameter or return position
// give rise to a "boxing bridge" method (which has the suffix `$adapted`).
// This is because Scala's unboxing of null values gives zero, whereas Java's throw a NPE.
// 1. Here we show that we are calling the boxing bridge (the lambda bodies here are compiled into
// methods of `(I)Ljava/lang/Object;` / `(I)Ljava/lang/Object;` respectively.)
- assertEquals("(Ljava/lang/Object;)Ljava/lang/Object;", implMethodDescriptorFor("(x: Int) => new Object"))
- assertEquals("(Ljava/lang/Object;)Ljava/lang/Object;", implMethodDescriptorFor("(x: Object) => 0"))
+ assertEquals(s"($obj)$obj", implMethodDescriptorFor("(x: Int) => new Object"))
+ assertEquals(s"($obj)$obj", implMethodDescriptorFor("(x: Object) => 0"))
// 2a. We don't need such adaptations for parameters or return values with types that differ
// from Object due to other generic substitution, LambdaMetafactory will downcast the arguments.
- assertEquals("(Ljava/lang/String;)Ljava/lang/String;", implMethodDescriptorFor("(x: String) => x"))
+ assertEquals(s"($str)$str", implMethodDescriptorFor("(x: String) => x"))
// 2b. Testing 2a. in combination with 1.
- assertEquals("(Ljava/lang/Object;)Ljava/lang/String;", implMethodDescriptorFor("(x: Int) => \"\""))
- assertEquals("(Ljava/lang/String;)Ljava/lang/Object;", implMethodDescriptorFor("(x: String) => 0"))
+ assertEquals(s"($obj)$str", implMethodDescriptorFor("(x: Int) => \"\""))
+ assertEquals(s"($str)$obj", implMethodDescriptorFor("(x: String) => 0"))
// 3. Specialized functions, don't need any of this as they implement a method like `apply$mcII$sp`,
// and the (un)boxing is handled in the base class in code emitted by scalac.
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 }")
+ assertEquals("(I)I", implMethodDescriptorFor("((x: VC) => x): FunVC"))
+
+ compileClasses(compiler)("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]]")
+
+ 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
new file mode 100644
index 0000000000..b9e45a7dc9
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/IndySammyTest.scala
@@ -0,0 +1,160 @@
+package scala.tools.nsc
+package backend.jvm
+
+import org.junit.Assert.assertEquals
+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 CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+
+import scala.tools.testing.ClearAfterClass
+
+object IndySammyTest extends ClearAfterClass.Clearable {
+ var _compiler = newCompiler()
+
+ def compile(scalaCode: String, javaCode: List[(String, String)] = Nil, allowMessage: StoreReporter#Info => Boolean = _ => false): List[ClassNode] =
+ compileClasses(_compiler)(scalaCode, javaCode, allowMessage)
+
+ def clear(): Unit = { _compiler = null }
+}
+
+@RunWith(classOf[JUnit4])
+class IndySammyTest extends ClearAfterClass {
+ ClearAfterClass.stateToClear = IndySammyTest
+ import IndySammyTest._
+
+ val compiler = _compiler
+
+ def funClassName(from: String, to: String) = s"Fun$from$to"
+ def classPrologue(from: String, to: String) =
+ "class VC(private val i: Int) extends AnyVal\n" +
+ s"trait ${funClassName(from, to)} { def apply(a: $from): $to}"
+
+ def lamDef(from: String, to: String, body: String => String) =
+ s"""def lam = (x => ${body("x")}): ${funClassName(from, to)}"""
+
+ def appDef(arg: String) = s"""def app = lam($arg)"""
+
+ /* Create a lambda of type "$from => $to" (with body "$body(x)" if "x" is the argument name),
+ * and apply it to `arg`.
+ *
+ * Check:
+ * - the signature of the apply method
+ * - the instructions in the lambda's body (anonfun method)
+ * - the instructions used to create the argument for the application
+ * (and the return corresponding to the lambda's result type)
+ */
+ 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 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
+
+ assertEquals(expectedSig, applySig)
+ assert(lamInsn.length == 2 && lamInsn.head.isInstanceOf[InvokeDynamic], lamInsn)
+ assertSameCode(anonfun, lamBody)
+ assertSameCode(applyInvoke, List(
+ VarOp(ALOAD, 0),
+ Invoke(INVOKEVIRTUAL, "C", "lam", s"()L${funClassName(from, to)};", false)) ++ appArgs ++ List(
+ Invoke(INVOKEINTERFACE, funClassName(from, to), "apply", applySig, true), ret)
+ )
+ }
+
+// 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 methodNodes = compileMethods(compiler)(s"def lam : $lamTp = $lam" +";"+ appDef(arg), allowMessage)
+//
+// val anonfun = methodNodes.filter(_.name contains "$anonfun$").map(convertMethod)
+// val lamInsn = methodNodes.find(_.name == "lam").map(instructionsFromMethod).get.dropNonOp
+// val applyInvoke = methodNodes.find(_.name == "app").map(convertMethod).get
+//
+// assert(lamInsn.length == 2 && lamInsn.head.isInstanceOf[InvokeDynamic], lamInsn)
+// assertSameCode(anonfun, lamBody)
+// assertSameCode(applyInvoke, List(
+// VarOp(ALOAD, 0),
+// Invoke(INVOKEVIRTUAL, "C", "lam", s"()L${funClassName(from, to)};", false)) ++ appArgs ++ List(
+// Invoke(INVOKEINTERFACE, funClassName(from, to), "apply", applySig, true), ret)
+// )
+// }
+
+ // x => x : VC => VC applied to VC(1)
+ @Test
+ def testVC_VC_VC =
+ test("VC", "VC", "new VC(1)")("(I)I",
+ List(VarOp(ILOAD, 0), Op(IRETURN)),
+ List(Op(ICONST_1)),
+ Op(IRETURN))()
+
+ // x => new VC(x) : Int => VC applied to 1
+ @Test
+ def testInt_VC_1 =
+ test("Int", "VC", "1", x => s"new VC($x)")("(I)I",
+ List(VarOp(ILOAD, 0), Op(IRETURN)),
+ List(Op(ICONST_1)),
+ Op(IRETURN))()
+
+ // x => x : VC => Int applied to VC(1)
+ @Test
+ def testVC_Int_VC =
+ test("VC", "Int", "new VC(1)", x => "1")("(I)I",
+ List(Op(ICONST_1), Op(IRETURN)),
+ List(Op(ICONST_1)),
+ Op(IRETURN))()
+
+ // x => new VC(1) : VC => Any applied to VC(1)
+ @Test
+ def testVC_Any_VC =
+ test("VC", "Any", "new VC(1)", x => s"new VC(1)")("(I)Ljava/lang/Object;",
+ List(TypeOp(NEW, "VC"), Op(DUP), Op(ICONST_1), Invoke(INVOKESPECIAL, "VC", "<init>", "(I)V", false), Op(ARETURN)),
+ List(Op(ICONST_1)),
+ Op(ARETURN))()
+
+
+ // x => x : VC => Unit applied to VC(1)
+ @Test
+ def testVC_Unit_VC =
+ test("VC", "Unit", "new VC(1)")("(I)V",
+ List(VarOp(ILOAD, 0), Op(POP), Op(RETURN)),
+ List(Op(ICONST_1)),
+ Op(RETURN))(allowMessage = _.msg.contains("pure expression"))
+
+ // x => new VC(x.asInstanceOf[Int]) : Any => VC applied to 1
+ //
+ // Scala:
+ // def lam = (x => new VC(x.asInstanceOf[Int])): FunAny_VC
+ // def app = lam(1)
+ // Java:
+ // FunAny_VC lam() { return x -> BoxesRunTime.unboxToInt((Object)x); }
+ // int app() { lam().apply(BoxesRunTime.boxToInteger((int)1));
+ @Test
+ def testAny_VC_1 =
+ test("Any", "VC", "1", x => s"new VC($x.asInstanceOf[Int])")("(Ljava/lang/Object;)I",
+ List(VarOp(ALOAD, 0), Invoke(INVOKESTATIC, "scala/runtime/BoxesRunTime", "unboxToInt", "(Ljava/lang/Object;)I", false), Op(IRETURN)),
+ List(Op(ICONST_1), Invoke(INVOKESTATIC, "scala/runtime/BoxesRunTime", "boxToInteger", "(I)Ljava/lang/Integer;", false)),
+ Op(IRETURN))()
+
+ // TODO
+ // x => x : Special[Int] applied to 1
+// @Test
+// def testSpecial_Int_1 =
+// testSpecial("x => x", "Special[Int]", "1")()
+
+
+ // Tests ThisReferringMethodsTraverser
+ @Test
+ def testStaticIfNoThisReference: Unit = {
+ val methodNodes = compileMethods(compiler)("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/opt/BTypesFromClassfileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala
index dfbedbaa25..1ce913006d 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala
@@ -67,14 +67,17 @@ class BTypesFromClassfileTest {
// there's a separate InlineInfoTest.
val chk1 = sameBTypes(fromSym.superClass, fromClassfile.superClass, checked)
+
+ // was:
+ // val chk2 = sameBTypes(fromSym.interfaces, fromClassfile.interfaces, chk1)
+ // TODO: The new trait encoding emits redundant parents in the backend to avoid linkage errors in invokespecial
+ // Need to give this some more thought, maybe do it earlier so it is reflected in the Symbol's info, too.
val fromSymInterfaces = fromSym.interfaces
val fromClassFileInterfaces = fromClassfile.interfaces
val (matching, other) = fromClassFileInterfaces.partition(x => fromSymInterfaces.exists(_.internalName == x.internalName))
val chk2 = sameBTypes(fromSym.interfaces, matching, chk1)
for (redundant <- other) {
- // TODO SD-86 The new trait encoding emits redundant parents in the backend to avoid linkage errors in invokespecial
- // Need to give this some more thought, maybe do it earlier so it is reflected in the Symbol's info, too.
assert(matching.exists(x => x.isSubtypeOf(redundant).orThrow), redundant)
}
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 6e1ac3ba9f..b37b5efa7e 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala
@@ -174,7 +174,7 @@ class CallGraphTest extends ClearAfterClass {
| def t2(i: Int, f: Int => Int, z: Int) = h(f) + i - z
| def t3(f: Int => Int) = h(x => f(x + 1))
|}
- |abstract class D {
+ |trait D {
| def iAmASam(x: Int): Int
| def selfSamCall = iAmASam(10)
|}
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 87794f1346..261d6beb96 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala
@@ -59,9 +59,7 @@ class InlineInfoTest extends ClearAfterClass {
|}
|class C extends T with U
""".stripMargin
-// val classes = compile(code) // SD-86
- InlineInfoTest.notPerRun.foreach(_.clear())
- val classes = compileClasses(compiler)(code, allowMessage = _ => true) // SD-86 inline warnings
+ val classes = compile(code)
val fromSyms = classes.map(c => compiler.genBCode.bTypes.classBTypeFromInternalName(c.name).info.get.inlineInfo)
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 3f95be8560..01d97855c8 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
@@ -67,10 +67,10 @@ class InlineWarningTest extends ClearAfterClass {
"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 _)})
- assert(count == 5, count) // TODO SD-85: 5th warning
+ assert(count == 4, count)
}
- // TODO SD-85: no more impl classes. this test (and the warning it tests!) can be removed
+ // TODO SD-86: no more impl classes. this test (and the warning it tests!) can be removed
@org.junit.Ignore @Test
def traitMissingImplClass(): Unit = {
val codeA = "trait T { @inline final def f = 1 }"
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 52e19b48fd..6562f81e4c 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala
@@ -42,15 +42,10 @@ class InlinerSeparateCompilationTest {
|}
""".stripMargin
- val warns = Set(
- "T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden",
- // TODO SD-85
- """O$::f()I is annotated @inline but could not be inlined:
- |The callee O$::f()I contains the instruction INVOKESPECIAL T.f ()I
- |that would cause an IllegalAccessError when inlined into class C""".stripMargin)
- val List(c, o, oMod, t) = compileClassesSeparately(List(codeA, codeB), args + " -Yopt-warnings", i => warns.exists(i.msg contains _))
+ 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")) // SD-85
+ assertNoInvoke(getSingleMethod(c, "t2"))
assertNoInvoke(getSingleMethod(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 e3e7103f46..9079ca248a 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
@@ -324,8 +324,6 @@ class InlinerTest extends ClearAfterClass {
|}
""".stripMargin
val List(c, t) = compile(code)
- println(textify(c))
- println(textify(t))
assertNoInvoke(getSingleMethod(c, "g"))
}
@@ -507,8 +505,7 @@ class InlinerTest extends ClearAfterClass {
"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 _)})
- // 3rd warnings because of mixin-method, see SD-86
- assert(count == 3, count)
+ assert(count == 2, count)
assertInvoke(getSingleMethod(c, "t1"), "T", "f")
assertInvoke(getSingleMethod(c, "t2"), "C", "f")
}
@@ -535,7 +532,7 @@ class InlinerTest extends ClearAfterClass {
|}
|object O extends T {
| @inline def g = 1
- | // mixin generates `def f = T$class.f(this)`, which is inlined here (we get ICONST_0)
+ | // mixin generates `def f = super[T].f`, which is inlined here (we get ICONST_0)
|}
|class C {
| def t1 = O.f // the mixin method of O is inlined, so we directly get the ICONST_0
@@ -543,19 +540,14 @@ class InlinerTest extends ClearAfterClass {
| def t3(t: T) = t.f // no inlining here
|}
""".stripMargin
- val warns = Set(
- "T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden",
- // SD-86 -- once the mixin-method O.f inlines the body of T.f, we can also inline O.g into class C.
- """O$::f()I is annotated @inline but could not be inlined:
- |The callee O$::f()I contains the instruction INVOKESPECIAL T.f ()I
- |that would cause an IllegalAccessError when inlined into class C""".stripMargin)
+ 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, oMirror, oModule, t) = compile(code, allowMessage = i => {count += 1; warns.exists(i.msg contains _)})
- assert(count == 3, count) // SD-86
+ val List(c, oMirror, oModule, t) = compile(code, allowMessage = i => {count += 1; i.msg contains warn})
+ assert(count == 1, count)
-// assertNoInvoke(getSingleMethod(oModule, "f")) // SD-86
+ assertNoInvoke(getSingleMethod(oModule, "f"))
-// assertNoInvoke(getSingleMethod(c, "t1")) // SD-86
+ assertNoInvoke(getSingleMethod(c, "t1"))
assertNoInvoke(getSingleMethod(c, "t2"))
assertInvoke(getSingleMethod(c, "t3"), "T", "f")
}
@@ -569,12 +561,10 @@ class InlinerTest extends ClearAfterClass {
|}
|trait Assembly extends T {
| @inline final def g = 1
- | @inline final def n = m // inlined. (*)
- | // (*) the declaration class of m is T. the signature of T$class.m is m(LAssembly;)I. so we need the self type to build the
- | // signature. then we can look up the MethodNode of T$class.m and then rewrite the INVOKEINTERFACE to INVOKESTATIC.
+ | @inline final def n = m // inlined (m is final)
|}
|class C {
- | def t1(a: Assembly) = a.f // like above, decl class is T, need self-type of T to rewrite the interface call to static.
+ | def t1(a: Assembly) = a.f // inlined (f is final)
| def t2(a: Assembly) = a.n
|}
""".stripMargin
@@ -618,30 +608,30 @@ class InlinerTest extends ClearAfterClass {
val code =
"""trait T1 {
| @inline def f: Int = 0
- | @inline def g1 = f // not inlined: f not final, so T1$class.g1 has an interface call T1.f
+ | @inline def g1 = f // not inlined: f not final
|}
|
- |// erased self-type (used in impl class for `self` parameter): T1
+ |// erased self-type: T1
|trait T2a { self: T1 with T2a =>
| @inline override final def f = 1
- | @inline def g2a = f // inlined: resolved as T2a.f, which is re-written to T2a$class.f, so T2a$class.g2a has ICONST_1
+ | @inline def g2a = f // inlined: resolved as T2a.f
|}
|
|final class Ca extends T1 with T2a {
- | // mixin generates accessors like `def g1 = T1$class.g1`, the impl class method call is inlined into the accessor.
+ | // mixin generates accessors like `def g1 = super[T1].g1`, the impl super call is inlined into the accessor.
|
| def m1a = g1 // call to accessor, inlined, we get the interface call T1.f
| def m2a = g2a // call to accessor, inlined, we get ICONST_1
| def m3a = f // call to accessor, inlined, we get ICONST_1
|
- | def m4a(t: T1) = t.f // T1.f is not final, so not inlined, interface call to T1.f
- | def m5a(t: T2a) = t.f // re-written to T2a$class.f, inlined, ICONST_1
+ | def m4a(t: T1) = t.f // T1.f is not final, so not inlined, we get an interface call T1.f
+ | def m5a(t: T2a) = t.f // inlined, we get ICONST_1
|}
|
|// erased self-type: T2b
|trait T2b { self: T2b with T1 =>
| @inline override final def f = 1
- | @inline def g2b = f // not inlined: resolved as T1.f, so T2b$class.g2b has an interface call T1.f
+ | @inline def g2b = f // not inlined: resolved as T1.f, we get an interface call T1.f
|}
|
|final class Cb extends T1 with T2b {
@@ -650,31 +640,26 @@ class InlinerTest extends ClearAfterClass {
| def m3b = f // inlined, we get ICONST_1
|
| def m4b(t: T1) = t.f // T1.f is not final, so not inlined, interface call to T1.f
- | def m5b(t: T2b) = t.f // re-written to T2b$class.f, inlined, ICONST_1
+ | def m5b(t: T2b) = t.f // inlined, ICONST_1
|}
""".stripMargin
- val warnings = Set(
- "T1::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden",
- "T2b::g2b()I is annotated @inline but cannot be inlined: the method is not final and may be overridden",
- "T1::g1()I is annotated @inline but cannot be inlined: the method is not final and may be overridden",
- "T2a::g2a()I is annotated @inline but cannot be inlined: the method is not final and may be overridden",
- "T1::g1()I is annotated @inline but cannot be inlined: the method is not final and may be overridden")
+ val warning = "T1::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden"
var count = 0
- val List(ca, cb, t1, t2a, t2b) = compile(code, allowMessage = i => {count += 1; warnings.exists(i.msg contains _)})
- assert(count == 8, count) // see comments, f is not inlined 4 times, additional warnings due to SD-86
+ 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")
-// assertInvoke(getSingleMethod(ca, "m1a"), "T1", "f") // disabled due to SD-86: m1a calls the mixin-method g1a, which calls super[T1].g1a. we inline the mixin-method and end up with the super call.
-// assertNoInvoke(getSingleMethod(ca, "m2a")) // no invoke, see comment on def g2a // SD-86
+ 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(getSingleMethod(cb, "m1b"), "T1", "f") // SD-86
-// assertInvoke(getSingleMethod(cb, "m2b"), "T1", "f") // invoke, see comment on def g2b // SD-86
+ 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"))
@@ -772,8 +757,8 @@ class InlinerTest extends ClearAfterClass {
| final val d = 3
| final val d1: Int = 3
|
- | @noinline def f = 5 // re-written to T$class
- | @noinline final def g = 6 // re-written
+ | @noinline def f = 5
+ | @noinline final def g = 6
|
| @noinline def h: Int
| @inline def i: Int
@@ -786,8 +771,8 @@ class InlinerTest extends ClearAfterClass {
| final val d = 3
| final val d1: Int = 3
|
- | @noinline def f = 5 // not re-written (not final)
- | @noinline final def g = 6 // re-written
+ | @noinline def f = 5
+ | @noinline final def g = 6
|
| @noinline def h: Int
| @inline def i: Int
@@ -1508,4 +1493,14 @@ class InlinerTest extends ClearAfterClass {
val List(a, b) = compileClassesSeparately(List(codeA, codeB), extraArgs = "-Yopt:l:project -Yopt-warnings")
assertInvoke(getSingleMethod(b, "t"), "A", "f")
}
+
+ @Test
+ def sd86(): Unit = {
+ val code =
+ """trait T { @inline def f = 1 } // note that f is not final
+ |class C extends T
+ """.stripMargin
+ val List(c, t) = compile(code, allowMessage = _ => true)
+ assertSameSummary(getSingleMethod(c, "f"), List(ICONST_1, IRETURN))
+ }
}
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 0ba0ecca4c..10ab006017 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala
@@ -100,7 +100,7 @@ class ScalaInlineInfoTest extends ClearAfterClass {
@Test
def inlineInfoSam(): Unit = {
val code =
- """abstract class C {
+ """trait C { // expected to be seen as sam: g(I)I
| def f = 0
| def g(x: Int): Int
| val foo = "hi"
@@ -108,10 +108,10 @@ class ScalaInlineInfoTest extends ClearAfterClass {
|abstract class D {
| val biz: Int
|}
- |trait T {
+ |trait T { // expected to be seen as sam: h(Ljava/lang/String;)I
| def h(a: String): Int
|}
- |abstract class E extends T {
+ |trait E extends T { // expected to be seen as sam: h(Ljava/lang/String;)I
| def hihi(x: Int) = x
|}
|class F extends T {
diff --git a/test/junit/scala/util/control/ExceptionTest.scala b/test/junit/scala/util/control/ExceptionTest.scala
new file mode 100644
index 0000000000..5211d31839
--- /dev/null
+++ b/test/junit/scala/util/control/ExceptionTest.scala
@@ -0,0 +1,42 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2016-2016, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.util
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import org.junit.Assert._
+
+import scala.collection.mutable.ListBuffer
+
+import scala.util.control.Exception._
+
+@RunWith(classOf[JUnit4])
+class ExceptionTest {
+
+ @Test
+ def andFinally(): Unit = {
+
+ locally {
+ val audit = ListBuffer[Int]()
+ val katch = nonFatalCatch[Unit].andFinally(audit append 1)
+ val result = katch(10)
+ assertEquals(result, 10)
+ assertEquals(audit.toList, 1 :: Nil)
+ }
+
+ locally {
+ val audit = ListBuffer[Int]()
+ val katch = nonFatalCatch[Unit].andFinally(audit append 1).andFinally(audit append 2)
+ val result = katch(20)
+ assertEquals(result, 20)
+ assertEquals(audit.toList, 1 :: 2 :: Nil)
+ }
+ }
+} \ No newline at end of file