From a8d97403928983f72db66c6dab1354e7c89fe343 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 6 Nov 2015 17:10:24 +0100 Subject: Rewrite test for SI-6956 --- .../nsc/transform/patmat/PatmatBytecodeTest.scala | 58 ++++++++++++++++++++++ test/pending/run/t6956.scala | 31 ------------ 2 files changed, 58 insertions(+), 31 deletions(-) create mode 100644 test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala delete mode 100644 test/pending/run/t6956.scala diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala new file mode 100644 index 0000000000..554e8c0150 --- /dev/null +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -0,0 +1,58 @@ +package scala.tools.nsc +package transform.patmat + +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.Test +import scala.tools.asm.Opcodes._ +import org.junit.Assert._ + +import scala.tools.nsc.backend.jvm.AsmUtils._ +import scala.tools.nsc.backend.jvm.CodeGenTools +import scala.tools.testing.AssertUtil._ + +import CodeGenTools._ +import scala.tools.partest.ASMConverters +import ASMConverters._ +import scala.tools.testing.ClearAfterClass + +object PatmatBytecodeTest extends ClearAfterClass.Clearable { + var compiler = newCompiler() + var optCompiler = newCompiler(extraArgs = "-Yopt:l:method") + def clear(): Unit = { compiler = null; optCompiler = null } +} + +@RunWith(classOf[JUnit4]) +class PatmatBytecodeTest extends ClearAfterClass { + ClearAfterClass.stateToClear = PatmatBytecodeTest + + val compiler = PatmatBytecodeTest.compiler + val optCompiler = PatmatBytecodeTest.optCompiler + + @Test + def t6956(): Unit = { + val code = + """class C { + | private[this] final val ONE = 1 + | + | def s1(i: Byte): Int = i match { + | case ONE => 1 + | case 2 => 2 + | case 3 => 3 + | case _ => 0 + | } + | + | def s2(i: Byte): Int = i match { + | case 1 => 1 + | case 2 => 2 + | case 3 => 3 + | case _ => 0 + | } + |} + """.stripMargin + + val List(c) = compileClasses(compiler)(code) + assert(getSingleMethod(c, "s1").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) + assert(getSingleMethod(c, "s2").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) + } +} diff --git a/test/pending/run/t6956.scala b/test/pending/run/t6956.scala deleted file mode 100644 index 57d721807d..0000000000 --- a/test/pending/run/t6956.scala +++ /dev/null @@ -1,31 +0,0 @@ -import scala.tools.partest.IcodeComparison - -class Switches { - private[this] final val ONE = 1 - - def switchBad(i: Byte): Int = i match { - case ONE => 1 - case 2 => 2 - case 3 => 3 - case _ => 0 - } - - def switchOkay(i: Byte): Int = i match { - case 1 => 1 - case 2 => 2 - case 3 => 3 - case _ => 0 - } -} - -object Test extends IcodeComparison { - // ensure we get two switches out of this -- ignore the rest of the output for robustness - // exclude the constant we emit for the "SWITCH ..." string below (we get the icode for all the code you see in this file) - override def show() = { - val expected = 2 - val actual = (collectIcode() filter { - x => x.indexOf("SWITCH ...") >= 0 && x.indexOf("CONSTANT(") == -1 - }).size - assert(actual == expected, s"switches expected: $expected, actual: $actual") - } -} -- cgit v1.2.3 From e49fda4fab463da13e084d1deeb6f1a58e0041d1 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 6 Nov 2015 17:12:26 +0100 Subject: Rewrite test for SI-6955 --- .../nsc/transform/patmat/PatmatBytecodeTest.scala | 28 ++++++++++++++++++ test/pending/run/t6955.scala | 33 ---------------------- 2 files changed, 28 insertions(+), 33 deletions(-) delete mode 100644 test/pending/run/t6955.scala diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index 554e8c0150..cccab3a6d7 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -55,4 +55,32 @@ class PatmatBytecodeTest extends ClearAfterClass { assert(getSingleMethod(c, "s1").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) assert(getSingleMethod(c, "s2").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) } + + @Test + def t6955(): Unit = { + val code = + """class C { + | type Tag = Byte + | + | def s1(i: Tag): Int = i match { // notice type of i is Tag = Byte + | case 1 => 1 + | case 2 => 2 + | case 3 => 3 + | case _ => 0 + | } + | + | // this worked before, should keep working + | def s2(i: Byte): Int = i match { + | case 1 => 1 + | case 2 => 2 + | case 3 => 3 + | case _ => 0 + | } + |} + """.stripMargin + + val List(c) = compileClasses(compiler)(code) + assert(getSingleMethod(c, "s1").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) + assert(getSingleMethod(c, "s2").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) + } } diff --git a/test/pending/run/t6955.scala b/test/pending/run/t6955.scala deleted file mode 100644 index 787617eff1..0000000000 --- a/test/pending/run/t6955.scala +++ /dev/null @@ -1,33 +0,0 @@ -import scala.tools.partest.IcodeComparison - -// this class should compile to code that uses switches (twice) -class Switches { - type Tag = Byte - - def switchBad(i: Tag): Int = i match { // notice type of i is Tag = Byte - case 1 => 1 - case 2 => 2 - case 3 => 3 - case _ => 0 - } - - // this worked before, should keep working - def switchOkay(i: Byte): Int = i match { - case 1 => 1 - case 2 => 2 - case 3 => 3 - case _ => 0 - } -} - -object Test extends IcodeComparison { - // ensure we get two switches out of this -- ignore the rest of the output for robustness - // exclude the constant we emit for the "SWITCH ..." string below (we get the icode for all the code you see in this file) - override def show() = { - val expected = 2 - val actual = (collectIcode() filter { - x => x.indexOf("SWITCH ...") >= 0 && x.indexOf("CONSTANT(") == -1 - }).size - assert(actual == expected, s"switches expected: $expected, actual: $actual") - } -} -- cgit v1.2.3 From 7b953e5a6c0239c7368b1b65364ab9cb96e012b3 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 25 Jan 2016 10:51:08 +0100 Subject: Rewrite test for SI-5313 --- .../nsc/backend/jvm/opt/MethodLevelOptsTest.scala | 93 +++++++++++++++++++++- test/pending/run/t5313.check | 12 --- test/pending/run/t5313.scala | 54 ------------- 3 files changed, 92 insertions(+), 67 deletions(-) delete mode 100644 test/pending/run/t5313.check delete mode 100644 test/pending/run/t5313.scala diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 46e1cebfc4..49b9924e97 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -15,9 +15,10 @@ import CodeGenTools._ import scala.tools.partest.ASMConverters import ASMConverters._ import scala.tools.testing.ClearAfterClass +import scala.collection.convert.decorateAsScala._ object MethodLevelOptsTest extends ClearAfterClass.Clearable { - var methodOptCompiler = newCompiler(extraArgs = "-Ybackend:GenBCode -Yopt:l:method") + var methodOptCompiler = newCompiler(extraArgs = "-Yopt:l:method") def clear(): Unit = { methodOptCompiler = null } } @@ -559,4 +560,94 @@ class MethodLevelOptsTest extends ClearAfterClass { getSingleMethod(c, "t").instructions.dropNonOp, List(VarOp(ALOAD, 1), Jump(IFNULL, Label(6)), Op(ICONST_1), Op(IRETURN), Label(6), Op(ICONST_0), Op(IRETURN))) } + + @Test + def t5313(): Unit = { + val code = + """class C { + | def randomBoolean = scala.util.Random.nextInt % 2 == 0 + | + | // 3 stores to kept1 (slot 1), 1 store to result (slot 2) + | def t1 = { + | var kept1 = new Object + | val result = new java.lang.ref.WeakReference(kept1) + | kept1 = null // we can't eliminate this assignment because result can observe + | // when the object has no more references. See SI-5313 + | kept1 = new Object // could eliminate this one with a more elaborate analysis (we know it contains null) + | // however, such is not implemented: if a var is live, then stores are kept. + | result + | } + | + | // only two variables are live: kept2 and kept3. they end up on slots 1 and 2. + | // kept2 has 2 stores, kept3 has 1 store. + | def t2 = { + | var erased2 = null // we can eliminate this store because it's never used + | val erased3 = erased2 // and this + | var erased4 = erased2 // and this + | val erased5 = erased4 // and this + | var kept2: Object = new Object // ultimately can't be eliminated + | while(randomBoolean) { + | val kept3 = kept2 + | kept2 = null // this can't, because it clobbers kept2, which is used + | erased4 = null // safe to eliminate + | println(kept3) + | } + | 0 + | } + | + | def t3 = { + | var kept4 = new Object // have to keep, it's used + | try + | println(kept4) + | catch { + | case _ : Throwable => kept4 = null // have to keep, it clobbers kept4 which is used + | } + | 0 + | } + | + | def t4 = { + | var kept5 = new Object + | print(kept5) + | kept5 = null // can't eliminate it's a clobber and it's used + | print(kept5) + | kept5 = null // eliminated by nullness analysis (store null to a local that is known to be null) + | 0 + | } + | + | def t5 = { + | while(randomBoolean) { + | var kept6: AnyRef = null // not used, but have to keep because it clobbers the next used store + | // on the back edge of the loop + | kept6 = new Object // used + | println(kept6) + | } + | 0 + | } + |} + """.stripMargin + + val List(c) = compileClasses(methodOptCompiler)(code) + def locals(m: String) = findAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2) + def stores(m: String) = getSingleMethod(c, m).instructions.filter(_.opcode == ASTORE) + + assertEquals(locals("t1"), List(("this",0), ("kept1",1), ("result",2))) + assert(stores("t1") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t1"))) + + assertEquals(locals("t2"), List(("this",0), ("kept2",1), ("kept3",2))) + assert(stores("t2") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t2"))) + + assertEquals(locals("t3"), List(("this",0), ("kept4",1))) + assert(stores("t3") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t3"))) + + assertEquals(locals("t4"), List(("this",0), ("kept5",1))) + assert(stores("t4") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t4"))) + + assertEquals(locals("t5"), List(("this",0), ("kept6",1))) + assert(stores("t5") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), + textify(findAsmMethod(c, "t5"))) + } } diff --git a/test/pending/run/t5313.check b/test/pending/run/t5313.check deleted file mode 100644 index 7a48b2b711..0000000000 --- a/test/pending/run/t5313.check +++ /dev/null @@ -1,12 +0,0 @@ -STORE_LOCAL(variable kept1) -STORE_LOCAL(value result) -STORE_LOCAL(variable kept1) -STORE_LOCAL(variable kept2) -STORE_LOCAL(value kept3) -STORE_LOCAL(variable kept2) -STORE_LOCAL(variable kept4) -STORE_LOCAL(variable kept4) -STORE_LOCAL(variable kept5) -STORE_LOCAL(variable kept5) -STORE_LOCAL(variable kept6) -STORE_LOCAL(variable kept6) diff --git a/test/pending/run/t5313.scala b/test/pending/run/t5313.scala deleted file mode 100644 index 4a5b076e6e..0000000000 --- a/test/pending/run/t5313.scala +++ /dev/null @@ -1,54 +0,0 @@ -import scala.tools.partest.IcodeComparison - -object Test extends IcodeComparison { - override def printIcodeAfterPhase = "dce" - - override def extraSettings: String = super.extraSettings + " -Yopt:l:classpath" - - override def code = - """class Foo { - def randomBoolean = scala.util.Random.nextInt % 2 == 0 - def bar = { - var kept1 = new Object - val result = new java.lang.ref.WeakReference(kept1) - kept1 = null // we can't eliminate this assignment because result can observe - // when the object has no more references. See SI-5313 - kept1 = new Object // but we can eliminate this one because kept1 has already been clobbered - var erased2 = null // we can eliminate this store because it's never used - val erased3 = erased2 // and this - var erased4 = erased2 // and this - val erased5 = erased4 // and this - var kept2: Object = new Object // ultimately can't be eliminated - while(randomBoolean) { - val kept3 = kept2 - kept2 = null // this can't, because it clobbers kept2, which is used - erased4 = null // safe to eliminate - println(kept3) - } - var kept4 = new Object // have to keep, it's used - try - println(kept4) - catch { - case _ : Throwable => kept4 = null // have to keep, it clobbers kept4 which is used - } - var kept5 = new Object - print(kept5) - kept5 = null // can't eliminate it's a clobber and it's used - print(kept5) - kept5 = null // can eliminate because we don't care about clobbers of nulls - while(randomBoolean) { - var kept6: AnyRef = null // not used, but have to keep because it clobbers the next used store - // on the back edge of the loop - kept6 = new Object // used - println(kept6) - } - result - } - }""".stripMargin - - override def show() { - val storeLocal = "STORE_LOCAL" - val lines1 = collectIcode() filter (_ contains storeLocal) map (x => x.drop(x.indexOf(storeLocal))) - println(lines1 mkString "\n") - } -} -- cgit v1.2.3 From 405ada956f6e8b4e765f0e56e61d9c954f868f18 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 25 Jan 2016 11:26:48 +0100 Subject: Rewrite copy propagation test --- .../nsc/backend/jvm/opt/MethodLevelOptsTest.scala | 79 ++++++++++++++-- test/pending/run/test-cpp.check | 81 ---------------- test/pending/run/test-cpp.scala | 104 --------------------- 3 files changed, 73 insertions(+), 191 deletions(-) delete mode 100644 test/pending/run/test-cpp.check delete mode 100644 test/pending/run/test-cpp.scala diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 49b9924e97..7e5dd734fd 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -8,6 +8,7 @@ import org.junit.Test import scala.tools.asm.Opcodes._ import org.junit.Assert._ +import scala.tools.asm.tree.ClassNode import scala.tools.nsc.backend.jvm.AsmUtils._ import scala.tools.testing.AssertUtil._ @@ -30,6 +31,8 @@ class MethodLevelOptsTest extends ClearAfterClass { def wrapInDefault(code: Instruction*) = List(Label(0), LineNumber(1, Label(0))) ::: code.toList ::: List(Label(1)) + def locals(c: ClassNode, m: String) = findAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2) + @Test def eliminateEmptyTry(): Unit = { val code = "def f = { try {} catch { case _: Throwable => 0; () }; 1 }" @@ -627,27 +630,91 @@ class MethodLevelOptsTest extends ClearAfterClass { """.stripMargin val List(c) = compileClasses(methodOptCompiler)(code) - def locals(m: String) = findAsmMethod(c, m).localVariables.asScala.toList.map(l => (l.name, l.index)).sortBy(_._2) def stores(m: String) = getSingleMethod(c, m).instructions.filter(_.opcode == ASTORE) - assertEquals(locals("t1"), List(("this",0), ("kept1",1), ("result",2))) + assertEquals(locals(c, "t1"), List(("this",0), ("kept1",1), ("result",2))) assert(stores("t1") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1), VarOp(ASTORE, 1)), textify(findAsmMethod(c, "t1"))) - assertEquals(locals("t2"), List(("this",0), ("kept2",1), ("kept3",2))) + assertEquals(locals(c, "t2"), List(("this",0), ("kept2",1), ("kept3",2))) assert(stores("t2") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 2), VarOp(ASTORE, 1)), textify(findAsmMethod(c, "t2"))) - assertEquals(locals("t3"), List(("this",0), ("kept4",1))) + assertEquals(locals(c, "t3"), List(("this",0), ("kept4",1))) assert(stores("t3") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), textify(findAsmMethod(c, "t3"))) - assertEquals(locals("t4"), List(("this",0), ("kept5",1))) + assertEquals(locals(c, "t4"), List(("this",0), ("kept5",1))) assert(stores("t4") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), textify(findAsmMethod(c, "t4"))) - assertEquals(locals("t5"), List(("this",0), ("kept6",1))) + assertEquals(locals(c, "t5"), List(("this",0), ("kept6",1))) assert(stores("t5") == List(VarOp(ASTORE, 1), VarOp(ASTORE, 1)), textify(findAsmMethod(c, "t5"))) } + + @Test + def testCpp(): Unit = { + // copied from an old test (run/test-cpp.scala) + val code = + """class C { + | import scala.util.Random._ + | + | def t1(x: Int) = { + | val y = x + | println(y) + | } + | + | def t2 = { + | val x = 2 + | val y = x + | println(y) + | } + | + | def t3 = { + | val x = this + | val y = x + | println(y) + | } + | + | def f = nextInt + | + | def t4 = { + | val x = f + | val y = x + | println(y) + | } + | + | def t5 = { + | var x = nextInt + | var y = x + | println(y) + | + | y = nextInt + | x = y + | println(x) + | } + |} + """.stripMargin + + val List(c) = compileClasses(methodOptCompiler)(code) + assertEquals(locals(c, "t1"), List(("this", 0), ("x", 1))) + + assertEquals(locals(c, "t2"), List(("this", 0), ("x", 1))) + // we don't have constant propagation (yet). + // the local var can't be optimized as a store;laod sequence, there's a GETSTATIC between the two + assertEquals( + textify(findAsmMethod(c, "t2")), + getSingleMethod(c, "t2").instructions.dropNonOp.map(_.opcode), + List( + ICONST_2, ISTORE, + GETSTATIC, // Predef.MODULE$ + ILOAD, INVOKESTATIC, // boxToInteger + INVOKEVIRTUAL, // println + RETURN)) + + assertEquals(locals(c, "t3"), List(("this", 0))) + assertEquals(locals(c, "t4"), List(("this", 0), ("x", 1))) + assertEquals(locals(c, "t5"), List(("this", 0), ("x", 1))) + } } diff --git a/test/pending/run/test-cpp.check b/test/pending/run/test-cpp.check deleted file mode 100644 index ff4c9bf2bf..0000000000 --- a/test/pending/run/test-cpp.check +++ /dev/null @@ -1,81 +0,0 @@ ---- a -+++ b -@@ -54,3 +54,3 @@ - def main(args: Array[String] (ARRAY[REF(class String)])): Unit { -- locals: value args, value x, value y -+ locals: value args - startBlock: 1 -@@ -59,10 +59,6 @@ - 1: -- 52 CONSTANT(2) -- 52 STORE_LOCAL(value x) - 52 SCOPE_ENTER value x -- 53 LOAD_LOCAL(value x) -- 53 STORE_LOCAL(value y) - 53 SCOPE_ENTER value y - 54 LOAD_MODULE object Predef -- 54 LOAD_LOCAL(value y) -+ 54 CONSTANT(2) - 54 BOX INT -@@ -109,3 +105,3 @@ - def main(args: Array[String] (ARRAY[REF(class String)])): Unit { -- locals: value args, value x, value y -+ locals: value args, value x - startBlock: 1 -@@ -118,7 +114,5 @@ - 81 SCOPE_ENTER value x -- 82 LOAD_LOCAL(value x) -- 82 STORE_LOCAL(value y) - 82 SCOPE_ENTER value y - 83 LOAD_MODULE object Predef -- 83 LOAD_LOCAL(value y) -+ 83 LOAD_LOCAL(value x) - 83 BOX INT -@@ -152,3 +146,3 @@ - def main(args: Array[String] (ARRAY[REF(class String)])): Unit { -- locals: value args, value x, value y -+ locals: value args - startBlock: 1 -@@ -157,10 +151,6 @@ - 1: -- 66 THIS(TestAliasChainDerefThis) -- 66 STORE_LOCAL(value x) - 66 SCOPE_ENTER value x -- 67 LOAD_LOCAL(value x) -- 67 STORE_LOCAL(value y) - 67 SCOPE_ENTER value y - 68 LOAD_MODULE object Predef -- 68 LOAD_LOCAL(value y) -+ 68 THIS(Object) - 68 CALL_METHOD scala.Predef.println (dynamic) -@@ -193,3 +183,3 @@ - def test(x: Int (INT)): Unit { -- locals: value x, value y -+ locals: value x - startBlock: 1 -@@ -198,7 +188,5 @@ - 1: -- 29 LOAD_LOCAL(value x) -- 29 STORE_LOCAL(value y) - 29 SCOPE_ENTER value y - 30 LOAD_MODULE object Predef -- 30 LOAD_LOCAL(value y) -+ 30 LOAD_LOCAL(value x) - 30 BOX INT -@@ -240,7 +228,5 @@ - 96 SCOPE_ENTER variable x -- 97 LOAD_LOCAL(variable x) -- 97 STORE_LOCAL(variable y) - 97 SCOPE_ENTER variable y - 98 LOAD_MODULE object Predef -- 98 LOAD_LOCAL(variable y) -+ 98 LOAD_LOCAL(variable x) - 98 BOX INT -@@ -250,6 +236,4 @@ - 100 STORE_LOCAL(variable y) -- 101 LOAD_LOCAL(variable y) -- 101 STORE_LOCAL(variable x) - 102 LOAD_MODULE object Predef -- 102 LOAD_LOCAL(variable x) -+ 102 LOAD_LOCAL(variable y) - 102 BOX INT diff --git a/test/pending/run/test-cpp.scala b/test/pending/run/test-cpp.scala deleted file mode 100644 index 4fca67d51e..0000000000 --- a/test/pending/run/test-cpp.scala +++ /dev/null @@ -1,104 +0,0 @@ -/** - * The only change is in the decision to replace a LOAD_LOCAL(l) - * in the copy-propagation performed before ClosureElimination. - * - * In the general case, the local variable 'l' is connected through - * an alias chain with other local variables and at the end of the - * alias chain there may be a Value, call it 'v'. - * - * If 'v' is cheaper to access (it is a Deref(This) or Const(_)), then - * replace the instruction to load it from the cheaper place. - * Otherwise, we use the local variable at the end of the alias chain - * instead of 'l'. - */ - -import scala.tools.partest.IcodeComparison - -object Test extends IcodeComparison { - override def printIcodeAfterPhase = "dce" -} - -import scala.util.Random._ - -/** - * The example in the bug report (Issue-5321): an alias chain which store - * an Unknown. Should remove local variable 'y'. - */ -object TestBugReport { - def test(x: Int) = { - val y = x - println(y) - } -} - -/** - * The code taken from scala.tools.nsc.settings.Settings: - * After inlining of the setter is performed, there is an opportunity for - * copy-propagation to eliminate some local variables. - */ -object TestSetterInline { - private var _postSetHook: this.type => Unit = (x: this.type) => () - def withPostSetHook(f: this.type => Unit): this.type = { _postSetHook = f ; this } -} - - -/** - * The access of the local variable 'y' should be replaced by the - * constant. - */ -object TestAliasChainConstant { - - def main(args: Array[String]): Unit = { - val x = 2 - val y = x - println(y) - } -} - -/** - * At the end of the alias chain we have a reference to 'this'. - * The local variables should be all discarded and replace by a - * direct reference to this - */ -class TestAliasChainDerefThis { - - def main(args: Array[String]): Unit = { - val x = this - val y = x - println(y) - } -} - -/** - * At the end of the alias chain, there is the value of a field. - * The use of variable 'y' should be replaced by 'x', not by an access - * to the field 'f' since it is more costly. - */ -object TestAliasChainDerefField { - def f = nextInt - - def main(args: Array[String]): Unit = { - val x = f - val y = x - println(y) - } -} - - -/** - * The first time 'println' is called, 'x' is replaced by 'y' - * and the second time, 'y' is replaced by 'x'. But none of them - * can be removed. - */ -object TestDifferentBindings { - - def main(args: Array[String]): Unit = { - var x = nextInt - var y = x - println(y) - - y = nextInt - x = y - println(x) - } -} -- cgit v1.2.3 From 9f7446450fec15d7563e5dcd0c12f56350951b7d Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 25 Jan 2016 10:56:53 +0100 Subject: Rewrite test for inlining from sealed class --- .../scala/tools/nsc/backend/jvm/CodeGenTools.scala | 2 +- .../tools/nsc/backend/jvm/opt/InlinerTest.scala | 28 +++++++++++++++ test/pending/pos/sealed-final.flags | 41 ---------------------- test/pending/pos/sealed-final.scala | 14 -------- 4 files changed, 29 insertions(+), 56 deletions(-) delete mode 100644 test/pending/pos/sealed-final.flags delete mode 100644 test/pending/pos/sealed-final.scala diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala index 69c3f69380..342f403426 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala @@ -48,7 +48,7 @@ object CodeGenTools { resetOutput(compiler) compiler } - + def newCompilerWithoutVirtualOutdir(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Global = { val settings = new Settings() val args = (CommandLineParser tokenize defaultArgs) ++ (CommandLineParser tokenize extraArgs) 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 192a036d5b..77133255f4 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -1468,4 +1468,32 @@ class InlinerTest extends ClearAfterClass { assertEquals(casts("t5"), Nil) assertEquals(casts("t6"), Nil) } + + @Test + def inlineFromSealed(): Unit = { + val code = + """sealed abstract class Foo { + | @inline def bar(x: Int) = x + 1 + |} + |object Foo { + | def mkFoo(): Foo = new Baz2 + |} + | + |object Baz1 extends Foo + |final class Baz2 extends Foo + | + |object Test { + | def f = Foo.mkFoo() bar 10 + |} + """.stripMargin + + val cls = compile(code) + val test = cls.find(_.name == "Test$").get + assertEquals( + getSingleMethod(test, "f").instructions.summary, + List(GETSTATIC, "mkFoo", + BIPUSH, ISTORE, + IFNONNULL, ACONST_NULL, ATHROW, -1 /*label*/, + ILOAD, ICONST_1, IADD, IRETURN)) + } } diff --git a/test/pending/pos/sealed-final.flags b/test/pending/pos/sealed-final.flags deleted file mode 100644 index 63d024a0ba..0000000000 --- a/test/pending/pos/sealed-final.flags +++ /dev/null @@ -1,41 +0,0 @@ --Xfatal-warnings -Yinline-warnings -Ybackend:GenASM -optimise -/* -The new flag settings could be - -Yopt-warnings -Yopt:l:project - -The issue here is that things are being inlined, but a lot of -redundant load/store instructions are left behind: - -2.11.7: - - public int f(); - Code: - 0: getstatic #19 // Field Foo$.MODULE$:LFoo$; - 3: invokevirtual #23 // Method Foo$.mkFoo:()LFoo; - 6: pop - 7: bipush 10 - 9: iconst_1 - 10: iadd - 11: ireturn - - -2.12.0-M3: - - public int f(); - Code: - 0: getstatic #19 // Field Foo$.MODULE$:LFoo$; - 3: invokevirtual #23 // Method Foo$.mkFoo:()LFoo; - 6: bipush 10 - 8: istore_2 - 9: dup - 10: ifnonnull 15 - 13: aconst_null - 14: athrow - 15: astore_1 - 16: iload_2 - 17: iconst_1 - 18: iadd - 19: istore_3 - 20: iload_3 - 21: ireturn -*/ \ No newline at end of file diff --git a/test/pending/pos/sealed-final.scala b/test/pending/pos/sealed-final.scala deleted file mode 100644 index bdedb5c1f6..0000000000 --- a/test/pending/pos/sealed-final.scala +++ /dev/null @@ -1,14 +0,0 @@ -sealed abstract class Foo { - @inline def bar(x: Int) = x + 1 -} -object Foo { - def mkFoo(): Foo = new Baz2 -} - -object Baz1 extends Foo -final class Baz2 extends Foo - -object Test { - // bar should be inlined now - def f = Foo.mkFoo() bar 10 -} -- cgit v1.2.3 From 062109b51d0dba640933d749bf07f55d84f450d4 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 9 Nov 2015 09:45:11 +0100 Subject: Rewrite test for inlining higher-order functions --- .../tools/nsc/backend/jvm/opt/InlinerTest.scala | 20 ++++++++ test/pending/pos/inliner2.flags | 35 ------------- test/pending/pos/inliner2.scala | 57 ---------------------- 3 files changed, 20 insertions(+), 92 deletions(-) delete mode 100644 test/pending/pos/inliner2.flags delete mode 100644 test/pending/pos/inliner2.scala 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 77133255f4..942b62b32c 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -1496,4 +1496,24 @@ class InlinerTest extends ClearAfterClass { IFNONNULL, ACONST_NULL, ATHROW, -1 /*label*/, ILOAD, ICONST_1, IADD, IRETURN)) } + + @Test // a test taken from the test suite for the 2.11 inliner + def oldInlineHigherOrderTest(): Unit = { + val code = + """class C { + | private var debug = false + | @inline private def ifelse[T](cond: => Boolean, ifPart: => T, elsePart: => T): T = if (cond) ifPart else elsePart + | final def t = ifelse(debug, 1, 2) + |} + """.stripMargin + val List(c) = compile(code) + val t = getSingleMethod(c, "t") + + // box-unbox will clean it up + assertEquals(getSingleMethod(c, "t").instructions.summary, + List( + ALOAD, "C$$$anonfun$1", IFEQ /*A*/, + "C$$$anonfun$2", IRETURN, + -1 /*A*/, "C$$$anonfun$3", IRETURN)) + } } diff --git a/test/pending/pos/inliner2.flags b/test/pending/pos/inliner2.flags deleted file mode 100644 index 4bf93a9c2a..0000000000 --- a/test/pending/pos/inliner2.flags +++ /dev/null @@ -1,35 +0,0 @@ --optimise -Ybackend:GenASM -Xfatal-warnings -/* -This is what we get with 2.11.2-M3 and -Yopt:l:project: - - public final int bob1(); - Code: - 0: aload_0 - 1: aload_0 - 2: astore 6 - 4: aload 6 - 6: invokedynamic #62, 0 // InvokeDynamic #0:apply$mcZ$sp:(LA;)Lscala/runtime/java8/JFunction0$mcZ$sp; - 11: checkcast #29 // class scala/Function0 - 14: invokedynamic #71, 0 // InvokeDynamic #1:apply$mcI$sp:()Lscala/runtime/java8/JFunction0$mcI$sp; - 19: checkcast #29 // class scala/Function0 - 22: invokedynamic #76, 0 // InvokeDynamic #2:apply$mcI$sp:()Lscala/runtime/java8/JFunction0$mcI$sp; - 27: checkcast #29 // class scala/Function0 - 30: astore 4 - 32: astore_3 - 33: astore_2 - 34: astore_1 - 35: aload_2 - 36: pop - 37: aload 6 - 39: invokevirtual #53 // Method A$$$anonfun$1:()Z - 42: ifeq 54 - 45: aload_3 - 46: invokeinterface #36, 1 // InterfaceMethod scala/Function0.apply:()Ljava/lang/Object; - 51: goto 61 - 54: aload 4 - 56: invokeinterface #36, 1 // InterfaceMethod scala/Function0.apply:()Ljava/lang/Object; - 61: astore 5 - 63: aload 5 - 65: invokestatic #82 // Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I - 68: ireturn -*/ \ No newline at end of file diff --git a/test/pending/pos/inliner2.scala b/test/pending/pos/inliner2.scala deleted file mode 100644 index bc83e04312..0000000000 --- a/test/pending/pos/inliner2.scala +++ /dev/null @@ -1,57 +0,0 @@ -// This isn't actually testing much, because no warning is emitted in versions -// before the fix which comes with this because the method isn't even considered -// for inlining due to the bug. -class A { - private var debug = false - @inline private def ifelse[T](cond: => Boolean, ifPart: => T, elsePart: => T): T = - if (cond) ifPart else elsePart - - final def bob1() = ifelse(debug, 1, 2) - final def bob2() = if (debug) 1 else 2 -} -// Cool: -// -// % ls -1 /tmp/2901/ -// A$$anonfun$bob1$1.class -// A$$anonfun$bob1$2.class -// A$$anonfun$bob1$3.class -// A.class -// % ls -1 /tmp/trunk -// A.class -// -// Observations: -// -// (1) The inlined version accesses the field: the explicit one calls the accessor. -// (2) The inlined version fails to eliminate boxing. With reference types it emits -// an unneeded checkcast. -// (3) The private var debug is mangled to A$$debug, but after inlining it is never accessed -// from outside of the class and doesn't need mangling. -// (4) We could forego emitting bytecode for ifelse entirely if it has been -// inlined at all sites. -// -// Generated bytecode for the above: -// -// public final int bob1(); -// Code: -// Stack=1, Locals=1, Args_size=1 -// 0: aload_0 -// 1: getfield #11; //Field A$$debug:Z -// 4: ifeq 14 -// 7: iconst_1 -// 8: invokestatic #41; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer; -// 11: goto 18 -// 14: iconst_2 -// 15: invokestatic #41; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer; -// 18: invokestatic #45; //Method scala/runtime/BoxesRunTime.unboxToInt:(Ljava/lang/Object;)I -// 21: ireturn -// -// public final int bob2(); -// Code: -// Stack=1, Locals=1, Args_size=1 -// 0: aload_0 -// 1: invokevirtual #48; //Method A$$debug:()Z -// 4: ifeq 11 -// 7: iconst_1 -// 8: goto 12 -// 11: iconst_2 -// 12: ireturn -- cgit v1.2.3 From 0210d265f900941a0c17bb73f8de4c784ab27fc0 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 9 Nov 2015 09:52:42 +0100 Subject: Rewrite test for SI-7006 --- .../nsc/backend/jvm/opt/MethodLevelOptsTest.scala | 24 ++++++++++++++++++ test/pending/jvm/t7006.check | 29 ---------------------- test/pending/jvm/t7006/Foo_1.flags | 1 - test/pending/jvm/t7006/Foo_1.scala | 10 -------- test/pending/jvm/t7006/Test.scala | 21 ---------------- 5 files changed, 24 insertions(+), 61 deletions(-) delete mode 100644 test/pending/jvm/t7006.check delete mode 100644 test/pending/jvm/t7006/Foo_1.flags delete mode 100644 test/pending/jvm/t7006/Foo_1.scala delete mode 100644 test/pending/jvm/t7006/Test.scala diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 7e5dd734fd..423ff85f04 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -717,4 +717,28 @@ class MethodLevelOptsTest extends ClearAfterClass { assertEquals(locals(c, "t4"), List(("this", 0), ("x", 1))) assertEquals(locals(c, "t5"), List(("this", 0), ("x", 1))) } + + @Test + def t7006(): Unit = { + val code = + """class C { + | def t: Unit = { + | try { + | val x = 3 + | } finally { + | print("hello") + | } + | while(true) { } + | } + |} + """.stripMargin + val List(c) = compileClasses(methodOptCompiler)(code) + val t = getSingleMethod(c, "t") + assertEquals(t.handlers, Nil) + assertEquals(locals(c, "t"), List(("this", 0))) + assertEquals(t.instructions.summary, + List( + GETSTATIC, LDC, "print", + -1, GOTO)) + } } diff --git a/test/pending/jvm/t7006.check b/test/pending/jvm/t7006.check deleted file mode 100644 index 6294b14d62..0000000000 --- a/test/pending/jvm/t7006.check +++ /dev/null @@ -1,29 +0,0 @@ -[running phase parser on Foo_1.scala] -[running phase namer on Foo_1.scala] -[running phase packageobjects on Foo_1.scala] -[running phase typer on Foo_1.scala] -[running phase patmat on Foo_1.scala] -[running phase superaccessors on Foo_1.scala] -[running phase extmethods on Foo_1.scala] -[running phase pickler on Foo_1.scala] -[running phase refchecks on Foo_1.scala] -[running phase uncurry on Foo_1.scala] -[running phase tailcalls on Foo_1.scala] -[running phase specialize on Foo_1.scala] -[running phase explicitouter on Foo_1.scala] -[running phase erasure on Foo_1.scala] -[running phase posterasure on Foo_1.scala] -[running phase lazyvals on Foo_1.scala] -[running phase lambdalift on Foo_1.scala] -[running phase constructors on Foo_1.scala] -[running phase flatten on Foo_1.scala] -[running phase mixin on Foo_1.scala] -[running phase cleanup on Foo_1.scala] -[running phase delambdafy on Foo_1.scala] -[running phase icode on Foo_1.scala] -[running phase inliner on Foo_1.scala] -[running phase inlinehandlers on Foo_1.scala] -[running phase closelim on Foo_1.scala] -[running phase constopt on Foo_1.scala] -[running phase dce on Foo_1.scala] -[running phase jvm on icode] diff --git a/test/pending/jvm/t7006/Foo_1.flags b/test/pending/jvm/t7006/Foo_1.flags deleted file mode 100644 index 5d1b6b2644..0000000000 --- a/test/pending/jvm/t7006/Foo_1.flags +++ /dev/null @@ -1 +0,0 @@ --Yopt:l:project -Ydebug -Xfatal-warnings diff --git a/test/pending/jvm/t7006/Foo_1.scala b/test/pending/jvm/t7006/Foo_1.scala deleted file mode 100644 index 3985557d9f..0000000000 --- a/test/pending/jvm/t7006/Foo_1.scala +++ /dev/null @@ -1,10 +0,0 @@ -class Foo_1 { - def foo { - try { - val x = 3 // this will be optimized away, leaving a useless jump only block - } finally { - print("hello") - } - while(true){} // ensure infinite loop doesn't break the algorithm - } -} diff --git a/test/pending/jvm/t7006/Test.scala b/test/pending/jvm/t7006/Test.scala deleted file mode 100644 index 7b4a8c45fb..0000000000 --- a/test/pending/jvm/t7006/Test.scala +++ /dev/null @@ -1,21 +0,0 @@ -import scala.tools.partest.BytecodeTest -import scala.tools.asm -import asm.tree.InsnList -import scala.collection.JavaConverters._ - -object Test extends BytecodeTest { - def show: Unit = { - val classNode = loadClassNode("Foo_1") - val methodNode = getMethod(classNode, "foo") - val nopCount = count(methodNode.instructions, asm.Opcodes.NOP) - val gotoCount = count(methodNode.instructions, asm.Opcodes.GOTO) - assert(nopCount == 0, s"NOPs expected: 0, actual: $nopCount") - assert(gotoCount == 1, s"GOTOs expected: 1, actual: $gotoCount") - } - - def count(insnList: InsnList, opcode: Int): Int = { - def isNop(node: asm.tree.AbstractInsnNode): Boolean = - (node.getOpcode == opcode) - insnList.iterator.asScala.count(isNop) - } -} -- cgit v1.2.3 From 454af8cfedb3a126ffc4de4fe01e0b3ebe538a77 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 9 Nov 2015 12:33:16 +0100 Subject: Rewrite test: no type test on primitives in patmat --- .../nsc/transform/patmat/PatmatBytecodeTest.scala | 19 +++++++++++++++++ .../jvm/patmat_opt_primitive_typetest.check | 1 - .../jvm/patmat_opt_primitive_typetest.flags | 1 - .../patmat_opt_primitive_typetest/Analyzed_1.scala | 24 ---------------------- .../jvm/patmat_opt_primitive_typetest/test.scala | 8 -------- 5 files changed, 19 insertions(+), 34 deletions(-) delete mode 100644 test/pending/jvm/patmat_opt_primitive_typetest.check delete mode 100644 test/pending/jvm/patmat_opt_primitive_typetest.flags delete mode 100644 test/pending/jvm/patmat_opt_primitive_typetest/Analyzed_1.scala delete mode 100644 test/pending/jvm/patmat_opt_primitive_typetest/test.scala diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index cccab3a6d7..b53f7693dc 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -83,4 +83,23 @@ class PatmatBytecodeTest extends ClearAfterClass { assert(getSingleMethod(c, "s1").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) assert(getSingleMethod(c, "s2").instructions.count(_.opcode == TABLESWITCH) == 1, textify(c)) } + + @Test + def optNoPrimitiveTypetest(): Unit = { + val code = + """case class Foo(x: Int, y: String) + |class C { + | def a = Foo(1, "a") match { + | case Foo(_: Int, y) => y + | } + |} + """.stripMargin + val c = compileClasses(optCompiler)(code).head + + assertEquals(textify(findAsmMethod(c, "a")), getSingleMethod(c, "a").instructions.summary, + List( + NEW, DUP, ICONST_1, LDC, "", + "y", ARETURN)) + } + } diff --git a/test/pending/jvm/patmat_opt_primitive_typetest.check b/test/pending/jvm/patmat_opt_primitive_typetest.check deleted file mode 100644 index 43f53aba12..0000000000 --- a/test/pending/jvm/patmat_opt_primitive_typetest.check +++ /dev/null @@ -1 +0,0 @@ -bytecode identical diff --git a/test/pending/jvm/patmat_opt_primitive_typetest.flags b/test/pending/jvm/patmat_opt_primitive_typetest.flags deleted file mode 100644 index 19c578e4ad..0000000000 --- a/test/pending/jvm/patmat_opt_primitive_typetest.flags +++ /dev/null @@ -1 +0,0 @@ --Yopt:l:project diff --git a/test/pending/jvm/patmat_opt_primitive_typetest/Analyzed_1.scala b/test/pending/jvm/patmat_opt_primitive_typetest/Analyzed_1.scala deleted file mode 100644 index c961082fa7..0000000000 --- a/test/pending/jvm/patmat_opt_primitive_typetest/Analyzed_1.scala +++ /dev/null @@ -1,24 +0,0 @@ -// this class's bytecode, compiled under -optimize is analyzed by the test -// method a's bytecode should be identical to method b's bytecode -class SameBytecode { - case class Foo(x: Int, y: String) - - def a = - Foo(1, "a") match { - case Foo(_: Int, y) => y - } - - // this method's body holds the tree that should be generated by the pattern matcher for method a (-Xprint:patmat) - // the test checks that bytecode for a and b is identical (modulo line numbers) - // we can't diff trees as they are quite different (patmat uses jumps to labels that cannot be expressed in source, for example) - // note that the actual tree is quite bad: we do an unnecessary null check, and local val (x3) - // some of these will be fixed soon (the initial null check is for the scrutinee, which is harder to fix in patmat) - def b: String = { - val x1 = Foo(1, "a") - if (x1.ne(null)) { - return x1.y - } - - throw new MatchError(x1) - } -} \ No newline at end of file diff --git a/test/pending/jvm/patmat_opt_primitive_typetest/test.scala b/test/pending/jvm/patmat_opt_primitive_typetest/test.scala deleted file mode 100644 index 2927e763d5..0000000000 --- a/test/pending/jvm/patmat_opt_primitive_typetest/test.scala +++ /dev/null @@ -1,8 +0,0 @@ -import scala.tools.partest.BytecodeTest - -object Test extends BytecodeTest { - def show: Unit = { - val classNode = loadClassNode("SameBytecode") - sameBytecode(getMethod(classNode, "a"), getMethod(classNode, "b")) - } -} -- cgit v1.2.3 From f4a74f7eefb0521c0531f930ac8fd505953e0f50 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 9 Nov 2015 12:44:07 +0100 Subject: Rewrite test: no null in patmat --- .../nsc/transform/patmat/PatmatBytecodeTest.scala | 13 ++++++++++++ test/pending/jvm/patmat_opt_no_nullcheck.check | 1 - test/pending/jvm/patmat_opt_no_nullcheck.flags | 1 - .../jvm/patmat_opt_no_nullcheck/Analyzed_1.scala | 24 ---------------------- .../pending/jvm/patmat_opt_no_nullcheck/test.scala | 14 ------------- 5 files changed, 13 insertions(+), 40 deletions(-) delete mode 100644 test/pending/jvm/patmat_opt_no_nullcheck.check delete mode 100644 test/pending/jvm/patmat_opt_no_nullcheck.flags delete mode 100644 test/pending/jvm/patmat_opt_no_nullcheck/Analyzed_1.scala delete mode 100644 test/pending/jvm/patmat_opt_no_nullcheck/test.scala diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index b53f7693dc..5aac1f4656 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -102,4 +102,17 @@ class PatmatBytecodeTest extends ClearAfterClass { "y", ARETURN)) } + @Test + def optNoNullCheck(): Unit = { + val code = + """case class Foo(x: Any) + |class C { + | def a = (Foo(1): Any) match { + | case Foo(_: String) => + | } + |} + """.stripMargin + val c = compileClasses(optCompiler)(code).head + assert(!getSingleMethod(c, "a").instructions.exists(i => i.opcode == IFNULL || i.opcode == IFNONNULL), textify(findAsmMethod(c, "a"))) + } } diff --git a/test/pending/jvm/patmat_opt_no_nullcheck.check b/test/pending/jvm/patmat_opt_no_nullcheck.check deleted file mode 100644 index 43f53aba12..0000000000 --- a/test/pending/jvm/patmat_opt_no_nullcheck.check +++ /dev/null @@ -1 +0,0 @@ -bytecode identical diff --git a/test/pending/jvm/patmat_opt_no_nullcheck.flags b/test/pending/jvm/patmat_opt_no_nullcheck.flags deleted file mode 100644 index 453b6b7895..0000000000 --- a/test/pending/jvm/patmat_opt_no_nullcheck.flags +++ /dev/null @@ -1 +0,0 @@ --Yopt:l:project \ No newline at end of file diff --git a/test/pending/jvm/patmat_opt_no_nullcheck/Analyzed_1.scala b/test/pending/jvm/patmat_opt_no_nullcheck/Analyzed_1.scala deleted file mode 100644 index 1e4d564cdf..0000000000 --- a/test/pending/jvm/patmat_opt_no_nullcheck/Analyzed_1.scala +++ /dev/null @@ -1,24 +0,0 @@ -// this class's bytecode, compiled under -optimize is analyzed by the test -// method a's bytecode should be identical to method b's bytecode -case class Foo(x: Any) - -class SameBytecode { - def a = - (Foo(1): Any) match { - case Foo(_: String) => - } - - // there's no null check - def b: Unit = { - val x1: Any = Foo(1) - if (x1.isInstanceOf[Foo]) { - val x3 = x1.asInstanceOf[Foo] - if (x3.x.isInstanceOf[String]) { - val x = () - return - } - } - - throw new MatchError(x1) - } -} \ No newline at end of file diff --git a/test/pending/jvm/patmat_opt_no_nullcheck/test.scala b/test/pending/jvm/patmat_opt_no_nullcheck/test.scala deleted file mode 100644 index 5a4a398b67..0000000000 --- a/test/pending/jvm/patmat_opt_no_nullcheck/test.scala +++ /dev/null @@ -1,14 +0,0 @@ -/* - * filter: inliner warning; re-run with - */ -import scala.tools.partest.{ BytecodeTest, ASMConverters } - -object Test extends BytecodeTest { - def show: Unit = { - val classNode = loadClassNode("SameBytecode") - // ASM and GenBCode assign variable slots slightly differently - val instrsA = ASMConverters.instructionsFromMethod(getMethod(classNode, "a")) - val instrsB = ASMConverters.instructionsFromMethod(getMethod(classNode, "b")) - assert(ASMConverters.equivalentBytecode(instrsA, instrsB), diffInstructions(instrsA, instrsB)) // doesn't work - } -} -- cgit v1.2.3 From ec8436306eba91635d022707166c1541e68ffb2c Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 9 Nov 2015 14:26:54 +0100 Subject: Rewrite test: no local for underscore --- .../nsc/transform/patmat/PatmatBytecodeTest.scala | 19 ++++++++++++++ .../pending/jvm/patmat_opt_ignore_underscore.check | 1 - .../pending/jvm/patmat_opt_ignore_underscore.flags | 1 - .../patmat_opt_ignore_underscore/Analyzed_1.scala | 29 ---------------------- .../jvm/patmat_opt_ignore_underscore/test.scala | 18 -------------- 5 files changed, 19 insertions(+), 49 deletions(-) delete mode 100644 test/pending/jvm/patmat_opt_ignore_underscore.check delete mode 100644 test/pending/jvm/patmat_opt_ignore_underscore.flags delete mode 100644 test/pending/jvm/patmat_opt_ignore_underscore/Analyzed_1.scala delete mode 100644 test/pending/jvm/patmat_opt_ignore_underscore/test.scala diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala index 5aac1f4656..cef27b4d87 100644 --- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala +++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala @@ -115,4 +115,23 @@ class PatmatBytecodeTest extends ClearAfterClass { val c = compileClasses(optCompiler)(code).head assert(!getSingleMethod(c, "a").instructions.exists(i => i.opcode == IFNULL || i.opcode == IFNONNULL), textify(findAsmMethod(c, "a"))) } + + @Test + def optNoLoacalForUnderscore(): Unit = { + val code = + """case class Foo(x: Any, y: String) + |class C { + | def a = Foo(1, "a") match { + | case Foo(_: String, y) => y + | } + |} + """.stripMargin + val c = compileClasses(optCompiler)(code).head + assertEquals(textify(findAsmMethod(c, "a")), getSingleMethod(c, "a").instructions.summary, + List(NEW, DUP, ICONST_1, "boxToInteger", LDC, "", ASTORE /*1*/, + ALOAD /*1*/, "y", ASTORE /*2*/, + ALOAD /*1*/, "x", INSTANCEOF, IFNE /*R*/, + NEW, DUP, ALOAD /*1*/, "", ATHROW, + /*R*/ -1, ALOAD /*2*/, ARETURN)) + } } diff --git a/test/pending/jvm/patmat_opt_ignore_underscore.check b/test/pending/jvm/patmat_opt_ignore_underscore.check deleted file mode 100644 index 43f53aba12..0000000000 --- a/test/pending/jvm/patmat_opt_ignore_underscore.check +++ /dev/null @@ -1 +0,0 @@ -bytecode identical diff --git a/test/pending/jvm/patmat_opt_ignore_underscore.flags b/test/pending/jvm/patmat_opt_ignore_underscore.flags deleted file mode 100644 index 453b6b7895..0000000000 --- a/test/pending/jvm/patmat_opt_ignore_underscore.flags +++ /dev/null @@ -1 +0,0 @@ --Yopt:l:project \ No newline at end of file diff --git a/test/pending/jvm/patmat_opt_ignore_underscore/Analyzed_1.scala b/test/pending/jvm/patmat_opt_ignore_underscore/Analyzed_1.scala deleted file mode 100644 index b0506018f6..0000000000 --- a/test/pending/jvm/patmat_opt_ignore_underscore/Analyzed_1.scala +++ /dev/null @@ -1,29 +0,0 @@ -// this class's bytecode, compiled under -optimize is analyzed by the test -// method a's bytecode should be identical to method b's bytecode -// this is not the best test for shielding against regressing on this particular issue, -// but it sets the stage for checking the bytecode emitted by the pattern matcher and -// comparing it to manually tuned code using if/then/else etc. -class SameBytecode { - case class Foo(x: Any, y: String) - - def a = - Foo(1, "a") match { - case Foo(_: String, y) => y - } - - // this method's body holds the tree that should be generated by the pattern matcher for method a (-Xprint:patmat) - // the test checks that bytecode for a and b is identical (modulo line numbers) - // we can't diff trees as they are quite different (patmat uses jumps to labels that cannot be expressed in source, for example) - // note that the actual tree is quite bad: we do an unnecessary null check, isInstanceOf and local val (x3) - // some of these will be fixed soon (the initial null check is for the scrutinee, which is harder to fix in patmat) - def b: String = { - val x1 = Foo(1, "a") - if (x1.ne(null)) { - if (x1.x.isInstanceOf[String]) { - return x1.y - } - } - - throw new MatchError(x1) - } -} \ No newline at end of file diff --git a/test/pending/jvm/patmat_opt_ignore_underscore/test.scala b/test/pending/jvm/patmat_opt_ignore_underscore/test.scala deleted file mode 100644 index d6630e80a0..0000000000 --- a/test/pending/jvm/patmat_opt_ignore_underscore/test.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* - * filter: inliner warning; re-run with - */ -import scala.tools.partest.BytecodeTest - -import scala.tools.nsc.util.JavaClassPath -import java.io.InputStream -import scala.tools.asm -import asm.ClassReader -import asm.tree.{ClassNode, InsnList} -import scala.collection.JavaConverters._ - -object Test extends BytecodeTest { - def show: Unit = { - val classNode = loadClassNode("SameBytecode") - sameBytecode(getMethod(classNode, "a"), getMethod(classNode, "b")) - } -} -- cgit v1.2.3 From 983894f24b6c79934af757173d9e44faecd34069 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 25 Jan 2016 11:58:34 +0100 Subject: Rename junit tests to end in *Test to make them run in ANT Our ANT script only runs junit tests that match *Test.class. https://github.com/scala/scala/blob/1081e718f8f8e174dbf615e42b157e187d3d3886/build.xml#L1467 --- .../junit/scala/collection/immutable/SetTest.scala | 81 ++++++++++++ .../scala/collection/immutable/SetTests.scala | 81 ------------ test/junit/scala/issues/BytecodeTest.scala | 136 ++++++++++++++++++++ test/junit/scala/issues/BytecodeTests.scala | 137 --------------------- test/junit/scala/reflect/ClassTag.scala | 29 ----- test/junit/scala/reflect/ClassTagTest.scala | 29 +++++ test/junit/scala/sys/process/t7350.scala | 1 - 7 files changed, 246 insertions(+), 248 deletions(-) create mode 100644 test/junit/scala/collection/immutable/SetTest.scala delete mode 100644 test/junit/scala/collection/immutable/SetTests.scala create mode 100644 test/junit/scala/issues/BytecodeTest.scala delete mode 100644 test/junit/scala/issues/BytecodeTests.scala delete mode 100644 test/junit/scala/reflect/ClassTag.scala create mode 100644 test/junit/scala/reflect/ClassTagTest.scala diff --git a/test/junit/scala/collection/immutable/SetTest.scala b/test/junit/scala/collection/immutable/SetTest.scala new file mode 100644 index 0000000000..4029c98009 --- /dev/null +++ b/test/junit/scala/collection/immutable/SetTest.scala @@ -0,0 +1,81 @@ +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 SetTest { + @Test + def test_SI8346_toSet_soundness(): Unit = { + val any2stringadd = "Disabled string conversions so as not to get confused!" + + def any[A](set: Set[A]): Set[Any] = { + val anyset = set.toSet[Any] + assert((anyset + "fish") contains "fish") + anyset + } + + // Make sure default immutable Set does not rebuild itself on widening with toSet + // Need to cover 0, 1, 2, 3, 4 elements as special cases + var si = Set.empty[Int] + assert(si eq si.toSet[Any]) + for (i <- 1 to 5) { + val s1 = Set(Array.range(1, i+1): _*) + val s2 = si + i + val s1a = any(s1) + val s2a = any(s2) + assert(s1 eq s1a) + assert(s2 eq s2a) + si = s2 + } + + // Make sure BitSet correctly rebuilds itself on widening with toSet + // Need to cover empty, values 0-63, values 0-127 as special cases + val bitsets = Seq(BitSet.empty, BitSet(23), BitSet(23, 99), BitSet(23, 99, 141)) + bitsets.foreach{ b => + val ba = any(b) + assert(b ne ba) + assertEquals(b, ba) + } + + // Make sure HashSet (and by extension, its implementing class HashTrieSet) + // does not rebuild itself on widening by toSet + val hashset = HashSet(1, 3, 5, 7) + val hashseta = any(hashset) + assert(hashset eq hashseta) + + // Make sure ListSet does not rebuild itself on widening by toSet + // (Covers Node also, since it subclasses ListSet) + val listset = ListSet(1, 3, 5, 7) + val listseta = any(listset) + assert(listset eq listseta) + + // Make sure SortedSets correctly rebuild themselves on widening with toSet + // Covers TreeSet and keySet of SortedMap also + val sortedsets = Seq( + SortedSet.empty[Int], SortedSet(5), SortedSet(1,2,3,5,4), + SortedMap(1 -> "cod", 2 -> "herring").keySet + ) + sortedsets.foreach{ set => + val seta = any(set) + assert(set ne seta) + assertEquals(set, seta) + } + + // Make sure ValueSets correctly rebuild themselves on widening with toSet + object WeekDay extends Enumeration { + type WeekDay = Value + val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value + } + val valuesa = any(WeekDay.values) + assert(WeekDay.values ne valuesa) + assertEquals(WeekDay.values, valuesa) + + // Make sure regular Map keySets do not rebuild themselves on widening with toSet + val mapset = Map(1 -> "cod", 2 -> "herring").keySet + val mapseta = any(mapset) + assert(mapset eq mapseta) + } +} diff --git a/test/junit/scala/collection/immutable/SetTests.scala b/test/junit/scala/collection/immutable/SetTests.scala deleted file mode 100644 index 28c7864359..0000000000 --- a/test/junit/scala/collection/immutable/SetTests.scala +++ /dev/null @@ -1,81 +0,0 @@ -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 SetTests { - @Test - def test_SI8346_toSet_soundness(): Unit = { - val any2stringadd = "Disabled string conversions so as not to get confused!" - - def any[A](set: Set[A]): Set[Any] = { - val anyset = set.toSet[Any] - assert((anyset + "fish") contains "fish") - anyset - } - - // Make sure default immutable Set does not rebuild itself on widening with toSet - // Need to cover 0, 1, 2, 3, 4 elements as special cases - var si = Set.empty[Int] - assert(si eq si.toSet[Any]) - for (i <- 1 to 5) { - val s1 = Set(Array.range(1, i+1): _*) - val s2 = si + i - val s1a = any(s1) - val s2a = any(s2) - assert(s1 eq s1a) - assert(s2 eq s2a) - si = s2 - } - - // Make sure BitSet correctly rebuilds itself on widening with toSet - // Need to cover empty, values 0-63, values 0-127 as special cases - val bitsets = Seq(BitSet.empty, BitSet(23), BitSet(23, 99), BitSet(23, 99, 141)) - bitsets.foreach{ b => - val ba = any(b) - assert(b ne ba) - assertEquals(b, ba) - } - - // Make sure HashSet (and by extension, its implementing class HashTrieSet) - // does not rebuild itself on widening by toSet - val hashset = HashSet(1, 3, 5, 7) - val hashseta = any(hashset) - assert(hashset eq hashseta) - - // Make sure ListSet does not rebuild itself on widening by toSet - // (Covers Node also, since it subclasses ListSet) - val listset = ListSet(1, 3, 5, 7) - val listseta = any(listset) - assert(listset eq listseta) - - // Make sure SortedSets correctly rebuild themselves on widening with toSet - // Covers TreeSet and keySet of SortedMap also - val sortedsets = Seq( - SortedSet.empty[Int], SortedSet(5), SortedSet(1,2,3,5,4), - SortedMap(1 -> "cod", 2 -> "herring").keySet - ) - sortedsets.foreach{ set => - val seta = any(set) - assert(set ne seta) - assertEquals(set, seta) - } - - // Make sure ValueSets correctly rebuild themselves on widening with toSet - object WeekDay extends Enumeration { - type WeekDay = Value - val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value - } - val valuesa = any(WeekDay.values) - assert(WeekDay.values ne valuesa) - assertEquals(WeekDay.values, valuesa) - - // Make sure regular Map keySets do not rebuild themselves on widening with toSet - val mapset = Map(1 -> "cod", 2 -> "herring").keySet - val mapseta = any(mapset) - assert(mapset eq mapseta) - } -} diff --git a/test/junit/scala/issues/BytecodeTest.scala b/test/junit/scala/issues/BytecodeTest.scala new file mode 100644 index 0000000000..7260f43c87 --- /dev/null +++ b/test/junit/scala/issues/BytecodeTest.scala @@ -0,0 +1,136 @@ +package scala.issues + +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.Test +import scala.tools.asm.Opcodes +import scala.tools.nsc.backend.jvm.AsmUtils +import scala.tools.nsc.backend.jvm.CodeGenTools._ +import org.junit.Assert._ +import scala.collection.JavaConverters._ +import scala.tools.partest.ASMConverters._ +import scala.tools.testing.ClearAfterClass + +object BytecodeTest extends ClearAfterClass.Clearable { + var compiler = newCompiler() + def clear(): Unit = { compiler = null } +} + +@RunWith(classOf[JUnit4]) +class BytecodeTest extends ClearAfterClass { + ClearAfterClass.stateToClear = BytecodeTest + val compiler = BytecodeTest.compiler + + @Test + def t8731(): Unit = { + val code = + """class C { + | def f(x: Int) = (x: @annotation.switch) match { + | case 1 => 0 + | case 2 => 1 + | case 3 => 2 + | } + | final val K = 10 + | def g(x: Int) = (x: @annotation.switch) match { + | case K => 0 + | case 1 => 10 + | case 2 => 20 + | } + |} + """.stripMargin + + val List(c) = compileClasses(compiler)(code) + + assertTrue(getSingleMethod(c, "f").instructions.count(_.isInstanceOf[TableSwitch]) == 1) + assertTrue(getSingleMethod(c, "g").instructions.count(_.isInstanceOf[LookupSwitch]) == 1) + } + + @Test + def t8926(): Unit = { + import scala.reflect.internal.util.BatchSourceFile + + // this test cannot be implemented using partest because of its mixed-mode compilation strategy: + // partest first compiles all files with scalac, then the java files, and then again the scala + // using the output classpath. this shadows the bug SI-8926. + + val annotA = + """import java.lang.annotation.Retention; + |import java.lang.annotation.RetentionPolicy; + |@Retention(RetentionPolicy.RUNTIME) + |public @interface AnnotA { } + """.stripMargin + val annotB = "public @interface AnnotB { }" + + val scalaSrc = + """@AnnotA class A + |@AnnotB class B + """.stripMargin + + val run = new compiler.Run() + run.compileSources(List(new BatchSourceFile("AnnotA.java", annotA), new BatchSourceFile("AnnotB.java", annotB), new BatchSourceFile("Test.scala", scalaSrc))) + val outDir = compiler.settings.outputDirs.getSingleOutput.get + val outfiles = (for (f <- outDir.iterator if !f.isDirectory) yield (f.name, f.toByteArray)).toList + + def check(classfile: String, annotName: String) = { + val f = (outfiles collect { case (`classfile`, bytes) => AsmUtils.readClass(bytes) }).head + val descs = f.visibleAnnotations.asScala.map(_.desc).toList + assertTrue(descs.toString, descs exists (_ contains annotName)) + } + + check("A.class", "AnnotA") + + // known issue SI-8928: the visibility of AnnotB should be CLASS, but annotation classes without + // a @Retention annotation are currently emitted as RUNTIME. + check("B.class", "AnnotB") + } + + @Test + def t6288bJumpPosition(): Unit = { + val code = + """object Case3 { // 01 + | def unapply(z: Any): Option[Int] = Some(-1) // 02 + | def main(args: Array[String]) { // 03 + | ("": Any) match { // 04 + | case x : String => // 05 + | println("case 0") // 06 println and jump at 6 + | case _ => // 07 + | println("default") // 08 println and jump at 8 + | } // 09 + | println("done") // 10 + | } + |} + """.stripMargin + val List(mirror, module) = compileClasses(compiler)(code) + + val unapplyLineNumbers = getSingleMethod(module, "unapply").instructions.filter(_.isInstanceOf[LineNumber]) + assert(unapplyLineNumbers == List(LineNumber(2, Label(0))), unapplyLineNumbers) + + import Opcodes._ + val expected = List( + LineNumber(4, Label(0)), + LineNumber(5, Label(5)), + Jump(IFNE, Label(11)), + Jump(GOTO, Label(20)), + + LineNumber(6, Label(11)), + Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), + Jump(GOTO, Label(33)), + + LineNumber(5, Label(20)), + Jump(GOTO, Label(24)), + + LineNumber(8, Label(24)), + Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), + Jump(GOTO, Label(33)), + + LineNumber(10, Label(33)), + Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false) + ) + + val mainIns = getSingleMethod(module, "main").instructions filter { + case _: LineNumber | _: Invoke | _: Jump => true + case _ => false + } + assertSameCode(mainIns, expected) + } +} diff --git a/test/junit/scala/issues/BytecodeTests.scala b/test/junit/scala/issues/BytecodeTests.scala deleted file mode 100644 index 7c446894df..0000000000 --- a/test/junit/scala/issues/BytecodeTests.scala +++ /dev/null @@ -1,137 +0,0 @@ -package scala.issues - -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import org.junit.Test -import scala.tools.asm.Opcodes -import scala.tools.nsc.backend.jvm.AsmUtils -import scala.tools.nsc.backend.jvm.CodeGenTools._ -import org.junit.Assert._ -import scala.collection.JavaConverters._ -import scala.tools.partest.ASMConverters._ -import scala.tools.testing.ClearAfterClass - -object BytecodeTests extends ClearAfterClass.Clearable { - var compiler = newCompiler() - def clear(): Unit = { compiler = null } -} - -@RunWith(classOf[JUnit4]) -class BytecodeTests extends ClearAfterClass { - ClearAfterClass.stateToClear = BytecodeTests - val compiler = BytecodeTests.compiler - - @Test - def t8731(): Unit = { - val code = - """class C { - | def f(x: Int) = (x: @annotation.switch) match { - | case 1 => 0 - | case 2 => 1 - | case 3 => 2 - | } - | final val K = 10 - | def g(x: Int) = (x: @annotation.switch) match { - | case K => 0 - | case 1 => 10 - | case 2 => 20 - | } - |} - """.stripMargin - - val List(c) = compileClasses(compiler)(code) - - assertTrue(getSingleMethod(c, "f").instructions.count(_.isInstanceOf[TableSwitch]) == 1) - assertTrue(getSingleMethod(c, "g").instructions.count(_.isInstanceOf[LookupSwitch]) == 1) - } - - @Test - def t8926(): Unit = { - import scala.reflect.internal.util.BatchSourceFile - - // this test cannot be implemented using partest because of its mixed-mode compilation strategy: - // partest first compiles all files with scalac, then the java files, and then again the scala - // using the output classpath. this shadows the bug SI-8926. - - val annotA = - """import java.lang.annotation.Retention; - |import java.lang.annotation.RetentionPolicy; - |@Retention(RetentionPolicy.RUNTIME) - |public @interface AnnotA { } - """.stripMargin - val annotB = "public @interface AnnotB { }" - - val scalaSrc = - """@AnnotA class A - |@AnnotB class B - """.stripMargin - - val run = new compiler.Run() - run.compileSources(List(new BatchSourceFile("AnnotA.java", annotA), new BatchSourceFile("AnnotB.java", annotB), new BatchSourceFile("Test.scala", scalaSrc))) - val outDir = compiler.settings.outputDirs.getSingleOutput.get - val outfiles = (for (f <- outDir.iterator if !f.isDirectory) yield (f.name, f.toByteArray)).toList - - def check(classfile: String, annotName: String) = { - val f = (outfiles collect { case (`classfile`, bytes) => AsmUtils.readClass(bytes) }).head - val descs = f.visibleAnnotations.asScala.map(_.desc).toList - assertTrue(descs.toString, descs exists (_ contains annotName)) - } - - check("A.class", "AnnotA") - - // known issue SI-8928: the visibility of AnnotB should be CLASS, but annotation classes without - // a @Retention annotation are currently emitted as RUNTIME. - check("B.class", "AnnotB") - } - - @Test - def t6288bJumpPosition(): Unit = { - val code = - """object Case3 { // 01 - | def unapply(z: Any): Option[Int] = Some(-1) // 02 - | def main(args: Array[String]) { // 03 - | ("": Any) match { // 04 - | case x : String => // 05 - | println("case 0") // 06 println and jump at 6 - | case _ => // 07 - | println("default") // 08 println and jump at 8 - | } // 09 - | println("done") // 10 - | } - |} - """.stripMargin - val List(mirror, module) = compileClasses(compiler)(code) - - val unapplyLineNumbers = getSingleMethod(module, "unapply").instructions.filter(_.isInstanceOf[LineNumber]) - assert(unapplyLineNumbers == List(LineNumber(2, Label(0))), unapplyLineNumbers) - - import Opcodes._ - val expected = List( - LineNumber(3, Label(0)), - LineNumber(4, Label(0)), - LineNumber(5, Label(5)), - Jump(IFNE, Label(11)), - Jump(GOTO, Label(20)), - - LineNumber(6, Label(11)), - Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), - Jump(GOTO, Label(33)), - - LineNumber(5, Label(20)), - Jump(GOTO, Label(24)), - - LineNumber(8, Label(24)), - Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false), - Jump(GOTO, Label(33)), - - LineNumber(10, Label(33)), - Invoke(INVOKEVIRTUAL, "scala/Predef$", "println", "(Ljava/lang/Object;)V", false) - ) - - val mainIns = getSingleMethod(module, "main").instructions filter { - case _: LineNumber | _: Invoke | _: Jump => true - case _ => false - } - assertSameCode(mainIns, expected) - } -} diff --git a/test/junit/scala/reflect/ClassTag.scala b/test/junit/scala/reflect/ClassTag.scala deleted file mode 100644 index 90cc981fc1..0000000000 --- a/test/junit/scala/reflect/ClassTag.scala +++ /dev/null @@ -1,29 +0,0 @@ -package scala.reflect - -import org.junit.Test -import org.junit.Assert._ -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 - -import scala.tools.testing.AssertUtil._ - -class Misc - -@RunWith(classOf[JUnit4]) -class ClassTagTest { - def checkNotString[A: ClassTag](a: Any) = a match { case x: String => false case x: A => true case _ => false } - def checkNotInt[A: ClassTag](a: Any) = a match { case x: Int => false case x: A => true case _ => false } - def checkNotLong[A: ClassTag](a: Any) = a match { case x: Long => false case x: A => true case _ => false } - - @Test def checkMisc = assertTrue(checkNotString[Misc](new Misc)) - @Test def checkString = assertTrue(checkNotInt[String] ("woele")) - @Test def checkByte = assertTrue(checkNotInt[Byte] (0.toByte)) - @Test def checkShort = assertTrue(checkNotInt[Short] (0.toShort)) - @Test def checkChar = assertTrue(checkNotInt[Char] (0.toChar)) - @Test def checkInt = assertTrue(checkNotLong[Int] (0.toInt)) - @Test def checkLong = assertTrue(checkNotInt[Long] (0.toLong)) - @Test def checkFloat = assertTrue(checkNotInt[Float] (0.toFloat)) - @Test def checkDouble = assertTrue(checkNotInt[Double] (0.toDouble)) - @Test def checkBoolean = assertTrue(checkNotInt[Boolean](false)) - @Test def checkUnit = assertTrue(checkNotInt[Unit] ({})) -} \ No newline at end of file diff --git a/test/junit/scala/reflect/ClassTagTest.scala b/test/junit/scala/reflect/ClassTagTest.scala new file mode 100644 index 0000000000..90cc981fc1 --- /dev/null +++ b/test/junit/scala/reflect/ClassTagTest.scala @@ -0,0 +1,29 @@ +package scala.reflect + +import org.junit.Test +import org.junit.Assert._ +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.testing.AssertUtil._ + +class Misc + +@RunWith(classOf[JUnit4]) +class ClassTagTest { + def checkNotString[A: ClassTag](a: Any) = a match { case x: String => false case x: A => true case _ => false } + def checkNotInt[A: ClassTag](a: Any) = a match { case x: Int => false case x: A => true case _ => false } + def checkNotLong[A: ClassTag](a: Any) = a match { case x: Long => false case x: A => true case _ => false } + + @Test def checkMisc = assertTrue(checkNotString[Misc](new Misc)) + @Test def checkString = assertTrue(checkNotInt[String] ("woele")) + @Test def checkByte = assertTrue(checkNotInt[Byte] (0.toByte)) + @Test def checkShort = assertTrue(checkNotInt[Short] (0.toShort)) + @Test def checkChar = assertTrue(checkNotInt[Char] (0.toChar)) + @Test def checkInt = assertTrue(checkNotLong[Int] (0.toInt)) + @Test def checkLong = assertTrue(checkNotInt[Long] (0.toLong)) + @Test def checkFloat = assertTrue(checkNotInt[Float] (0.toFloat)) + @Test def checkDouble = assertTrue(checkNotInt[Double] (0.toDouble)) + @Test def checkBoolean = assertTrue(checkNotInt[Boolean](false)) + @Test def checkUnit = assertTrue(checkNotInt[Unit] ({})) +} \ No newline at end of file diff --git a/test/junit/scala/sys/process/t7350.scala b/test/junit/scala/sys/process/t7350.scala index 3c0e5145e6..9fdcac8ccc 100644 --- a/test/junit/scala/sys/process/t7350.scala +++ b/test/junit/scala/sys/process/t7350.scala @@ -1,4 +1,3 @@ - package scala.sys.process import org.junit.runner.RunWith -- cgit v1.2.3