summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@typesafe.com>2016-04-07 21:59:32 +0200
committerLukas Rytz <lukas.rytz@typesafe.com>2016-04-07 21:59:32 +0200
commitd6f66ec0f38e42c19f79cbe9d32d29c65dee1e05 (patch)
tree3a517ac17158c218b1e07f9c81e1af116da3df08 /test
parenta326ef408084ed4aab860572d07222abe80b461d (diff)
parent17d97067a72b15c33a249dd201f3af452e3bb3ab (diff)
downloadscala-d6f66ec0f38e42c19f79cbe9d32d29c65dee1e05.tar.gz
scala-d6f66ec0f38e42c19f79cbe9d32d29c65dee1e05.tar.bz2
scala-d6f66ec0f38e42c19f79cbe9d32d29c65dee1e05.zip
Merge pull request #5082 from lrytz/inlineImplClassCleanup
Cleanups related to the removal of trait impl classes
Diffstat (limited to 'test')
-rw-r--r--test/files/jvm/innerClassAttribute/Classes_1.scala19
-rw-r--r--test/files/jvm/innerClassAttribute/Test.scala6
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala24
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala97
4 files changed, 91 insertions, 55 deletions
diff --git a/test/files/jvm/innerClassAttribute/Classes_1.scala b/test/files/jvm/innerClassAttribute/Classes_1.scala
index 0abed140f1..bffc495b4f 100644
--- a/test/files/jvm/innerClassAttribute/Classes_1.scala
+++ b/test/files/jvm/innerClassAttribute/Classes_1.scala
@@ -186,7 +186,7 @@ trait A24 extends A24Base {
}
}
-class SI_9105 {
+class SI_9105 {
// outerClass enclMeth
val fun = (s: String) => {
class A // SI_9105 null
@@ -269,6 +269,23 @@ class SpecializedClassesAreTopLevel {
// }
}
+object AnonymousClassesMayBeNestedInSpecialized {
+ abstract class A
+ class C[@specialized(Int) T] {
+ def foo(t: T): A = new A { }
+ }
+
+ // specialization duplicates the anonymous class, one copy is nested in the specialized subclass of C
+
+ // class C$mcI$sp extends C[Int] {
+ // override def foo(t: Int): A = C$mcI$sp.this.foo$mcI$sp(t);
+ // override def foo$mcI$sp(t: Int): A = {
+ // final class $anon extends A { }
+ // new <$anon: A>()
+ // }
+ // }
+}
+
object NestedInValueClass {
// note that we can only test anonymous functions, nested classes are not allowed inside value classes
class A(val arg: String) extends AnyVal {
diff --git a/test/files/jvm/innerClassAttribute/Test.scala b/test/files/jvm/innerClassAttribute/Test.scala
index 1ac5a2dcf6..1b78773d42 100644
--- a/test/files/jvm/innerClassAttribute/Test.scala
+++ b/test/files/jvm/innerClassAttribute/Test.scala
@@ -414,6 +414,11 @@ object Test extends BytecodeTest {
List("SpecializedClassesAreTopLevel$T$", "SpecializedClassesAreTopLevel$T$B$mcI$sp", "SpecializedClassesAreTopLevel$T$B").foreach(testInner(_, t, b))
}
+ def testAnonymousClassesMayBeNestedInSpecialized() {
+ assertEnclosingMethod("AnonymousClassesMayBeNestedInSpecialized$C$$anon$17", "AnonymousClassesMayBeNestedInSpecialized$C", "foo", "(Ljava/lang/Object;)LAnonymousClassesMayBeNestedInSpecialized$A;")
+ assertEnclosingMethod("AnonymousClassesMayBeNestedInSpecialized$C$mcI$sp$$anon$18", "AnonymousClassesMayBeNestedInSpecialized$C$mcI$sp", "foo$mcI$sp", "(I)LAnonymousClassesMayBeNestedInSpecialized$A;")
+ }
+
def testNestedInValueClass() {
List(
"NestedInValueClass",
@@ -466,6 +471,7 @@ object Test extends BytecodeTest {
testSI_9124()
testImplClassesTopLevel()
testSpecializedClassesTopLevel()
+ testAnonymousClassesMayBeNestedInSpecialized()
testNestedInValueClass()
}
}
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 01d97855c8..90236265e6 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
@@ -70,30 +70,6 @@ class InlineWarningTest extends ClearAfterClass {
assert(count == 4, count)
}
- // 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 }"
- val codeB = "class C { def t1(t: T) = t.f }"
-
- val removeImpl = (outDir: AbstractFile) => {
- val f = outDir.lookupName("T$class.class", directory = false)
- if (f != null) f.delete()
- }
-
- val warn =
- """T::f()I is annotated @inline but cannot be inlined: the trait method call could not be rewritten to the static implementation method. Possible reason:
- |The method f(LT;)I could not be found in the class T$class or any of its parents.
- |Note that the following parent classes could not be found on the classpath: T$class""".stripMargin
-
- var c = 0
- compileSeparately(List(codeA, codeB), extraArgs = InlineWarningTest.args, afterEach = removeImpl, allowMessage = i => {c += 1; i.msg contains warn})
- assert(c == 1, c)
-
- // only summary here
- compileSeparately(List(codeA, codeB), extraArgs = InlineWarningTest.argsNoWarn, afterEach = removeImpl, allowMessage = _.msg contains "there was one inliner warning")
- }
-
@Test
def handlerNonEmptyStack(): Unit = {
val code =
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 10ab006017..4db2657c1b 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala
@@ -29,12 +29,24 @@ class ScalaInlineInfoTest extends ClearAfterClass {
def inlineInfo(c: ClassNode): InlineInfo = c.attrs.asScala.collect({ case a: InlineInfoAttribute => a.inlineInfo }).head
+ def mapDiff[A, B](a: Map[A, B], b: Map[A, B]) = {
+ val r = new StringBuilder
+ for ((a, av) <- a) {
+ if (!b.contains(a)) r.append(s"missing in b: $a\n")
+ else if (av != b(a)) r.append(s"different for $a: $av != ${b(a)}\n")
+ }
+ for (b <- b.keys.toList diff a.keys.toList) {
+ r.append(s"missing in a: $b\n")
+ }
+ r.toString
+ }
+
@Test
def traitMembersInlineInfo(): Unit = {
val code =
"""trait T {
| def f1 = 1 // concrete method
- | private def f2 = 1 // implOnly method (does not end up in the interface)
+ | private def f2 = 1 // default method only (not in subclass)
| def f3 = {
| def nest = 0 // nested method (does not end up in the interface)
| nest
@@ -44,13 +56,13 @@ class ScalaInlineInfoTest extends ClearAfterClass {
| def f4 = super.toString // super accessor
|
| object O // module accessor (method is generated)
- | def f5 = {
+ | final def f5 = {
| object L { val x = 0 } // nested module (just flattened out)
| L.x
| }
|
| @noinline
- | def f6: Int // abstract method (not in impl class)
+ | def f6: Int // abstract method
|
| // fields
|
@@ -61,40 +73,65 @@ class ScalaInlineInfoTest extends ClearAfterClass {
|
| final val x5 = 0
|}
+ |class C extends T {
+ | def f6 = 0
+ | var x3 = 0
+ |}
""".stripMargin
- val cs @ List(t, tl, to) = compileClasses(compiler)(code)
- val info = inlineInfo(t)
- val expect = InlineInfo (
- None, // self type
+ val cs @ List(c, t, tl, to) = compileClasses(compiler)(code)
+ val infoT = inlineInfo(t)
+ val expectT = InlineInfo (
false, // final class
None, // not a sam
Map(
- // TODO SD-86: the module accessor used to be `effectivelyFinal` before nuke-impl-classes
- ("O()LT$O$;", MethodInlineInfo(false,false,false,false)),
- ("T$$super$toString()Ljava/lang/String;", MethodInlineInfo(false,false,false,false)),
- ("T$_setter_$x1_$eq(I)V", MethodInlineInfo(false,false,false,false)),
- ("f1()I", MethodInlineInfo(false,false,false,false)),
- ("f3()I", MethodInlineInfo(false,false,false,false)),
- ("f4()Ljava/lang/String;", MethodInlineInfo(false,false,true, false)),
- ("f5()I", MethodInlineInfo(false,false,false,false)),
- ("f6()I", MethodInlineInfo(false,false,false,true )),
- ("x1()I", MethodInlineInfo(false,false,false,false)),
- ("x3()I", MethodInlineInfo(false,false,false,false)),
- ("x3_$eq(I)V", MethodInlineInfo(false,false,false,false)),
- ("x4()I", MethodInlineInfo(false,false,false,false)),
- ("x5()I", MethodInlineInfo(true, false,false,false)),
- ("y2()I", MethodInlineInfo(false,false,false,false)),
- ("y2_$eq(I)V", MethodInlineInfo(false,false,false,false)),
- ("f2()I", MethodInlineInfo(true, false,false,false)),
- ("L$lzycompute$1(Lscala/runtime/VolatileObjectRef;)LT$L$2$;",MethodInlineInfo(true, false,false,false)),
- // TODO SD-86: should probably be effectivelyFinal
- ("L$1(Lscala/runtime/VolatileObjectRef;)LT$L$2$;", MethodInlineInfo(false,false,false,false)),
- ("nest$1()I", MethodInlineInfo(true, false,false,false)),
- ("$init$()V", MethodInlineInfo(false,false,false,false))),
+ ("O()LT$O$;", MethodInlineInfo(true ,false,false)), // the accessor is abstract in bytecode, but still effectivelyFinal because there's no (late)DEFERRED flag, https://github.com/scala/scala-dev/issues/126
+ ("T$$super$toString()Ljava/lang/String;", MethodInlineInfo(true ,false,false)),
+ ("T$_setter_$x1_$eq(I)V", MethodInlineInfo(false,false,false)),
+ ("f1()I", MethodInlineInfo(false,false,false)),
+ ("f2()I", MethodInlineInfo(true, false,false)),
+ ("f3()I", MethodInlineInfo(false,false,false)),
+ ("f4()Ljava/lang/String;", MethodInlineInfo(false,true, false)),
+ ("f5()I", MethodInlineInfo(true ,false,false)),
+ ("f6()I", MethodInlineInfo(false,false,true )),
+ ("x1()I", MethodInlineInfo(false,false,false)),
+ ("y2()I", MethodInlineInfo(false,false,false)),
+ ("y2_$eq(I)V", MethodInlineInfo(false,false,false)),
+ ("x3()I", MethodInlineInfo(false,false,false)),
+ ("x3_$eq(I)V", MethodInlineInfo(false,false,false)),
+ ("x4()I", MethodInlineInfo(false,false,false)),
+ ("x5()I", MethodInlineInfo(true, false,false)),
+ ("L$lzycompute$1(Lscala/runtime/VolatileObjectRef;)LT$L$2$;", MethodInlineInfo(true, false,false)),
+ ("L$1(Lscala/runtime/VolatileObjectRef;)LT$L$2$;", MethodInlineInfo(true ,false,false)),
+ ("nest$1()I", MethodInlineInfo(true, false,false)),
+ ("$init$()V", MethodInlineInfo(false,false,false))),
None // warning
)
- assert(info == expect, info)
+
+ assert(infoT == expectT, mapDiff(expectT.methodInfos, infoT.methodInfos) + infoT)
+
+ val infoC = inlineInfo(c)
+ val expectC = InlineInfo(false, None, Map(
+ "O()LT$O$;" -> MethodInlineInfo(true ,false,false),
+ "f1()I" -> MethodInlineInfo(false,false,false),
+ "f3()I" -> MethodInlineInfo(false,false,false),
+ "f4()Ljava/lang/String;" -> MethodInlineInfo(false,true ,false),
+ "f5()I" -> MethodInlineInfo(true ,false,false),
+ "f6()I" -> MethodInlineInfo(false,false,false),
+ "x1()I" -> MethodInlineInfo(false,false,false),
+ "T$_setter_$x1_$eq(I)V" -> MethodInlineInfo(false,false,false),
+ "y2()I" -> MethodInlineInfo(false,false,false),
+ "y2_$eq(I)V" -> MethodInlineInfo(false,false,false),
+ "x3()I" -> MethodInlineInfo(false,false,false),
+ "x3_$eq(I)V" -> MethodInlineInfo(false,false,false),
+ "x4$lzycompute()I" -> MethodInlineInfo(true ,false,false),
+ "x4()I" -> MethodInlineInfo(false,false,false),
+ "x5()I" -> MethodInlineInfo(true ,false,false),
+ "T$$super$toString()Ljava/lang/String;" -> MethodInlineInfo(true ,false,false),
+ "<init>()V" -> MethodInlineInfo(false,false,false)),
+ None)
+
+ assert(infoC == expectC, mapDiff(expectC.methodInfos, infoC.methodInfos) + infoC)
}
@Test