diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2015-02-09 19:33:20 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2015-03-11 15:18:22 -0700 |
commit | a4e71b188fe8069b4de3a0753defb624b8b1eb8c (patch) | |
tree | 1db043db5e1a84568595413fc5c2ea77679ae0eb /test | |
parent | f8bb3d5289e5eb84ccd94386e5c3df1bdf8b91bc (diff) | |
download | scala-a4e71b188fe8069b4de3a0753defb624b8b1eb8c.tar.gz scala-a4e71b188fe8069b4de3a0753defb624b8b1eb8c.tar.bz2 scala-a4e71b188fe8069b4de3a0753defb624b8b1eb8c.zip |
Cast receiver if necessary when rewriting trait calls to impl method
The self parameter type may be incompatible with the trait type.
trait T { self: S => def foo = 1 }
The $self parameter type of T$class.foo is S, which may be unrelated
to T. If we re-write a call to T.foo to T$class.foo, we need to cast
the receiver to S, otherwise we get a VerifyError.
Diffstat (limited to 'test')
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala | 1 | ||||
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala | 25 |
2 files changed, 21 insertions, 5 deletions
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 16f09db189..d7344ae61f 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala @@ -11,7 +11,6 @@ import org.junit.Assert._ import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ -import scala.tools.nsc.backend.jvm.opt.BytecodeUtils.BasicAnalyzer import scala.tools.testing.AssertUtil._ import CodeGenTools._ 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 694dff8dee..7f58f77b15 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala @@ -13,7 +13,7 @@ import org.junit.Assert._ import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ -import scala.tools.nsc.backend.jvm.opt.BytecodeUtils.BasicAnalyzer +import scala.tools.nsc.backend.jvm.opt.BytecodeUtils.AsmAnalyzer import scala.tools.nsc.io._ import scala.tools.testing.AssertUtil._ @@ -84,7 +84,7 @@ class InlinerTest extends ClearAfterClass { val List(f, g) = cls.methods.asScala.filter(m => Set("f", "g")(m.name)).toList.sortBy(_.name) val fCall = g.instructions.iterator.asScala.collect({ case i: MethodInsnNode if i.name == "f" => i }).next() - val analyzer = new BasicAnalyzer(g, clsBType.internalName) + val analyzer = new AsmAnalyzer(g, clsBType.internalName) val r = inliner.inline( fCall, @@ -222,7 +222,7 @@ class InlinerTest extends ClearAfterClass { case m: MethodInsnNode if m.name == "g" => m }).next() - val analyzer = new BasicAnalyzer(h, dTp.internalName) + val analyzer = new AsmAnalyzer(h, dTp.internalName) val r = inliner.inline( gCall, @@ -374,7 +374,7 @@ class InlinerTest extends ClearAfterClass { val f = c.methods.asScala.find(_.name == "f").get val callsiteIns = f.instructions.iterator().asScala.collect({ case c: MethodInsnNode => c }).next() val clsBType = classBTypeFromParsedClassfile(c.name).get - val analyzer = new BasicAnalyzer(f, clsBType.internalName) + val analyzer = new AsmAnalyzer(f, clsBType.internalName) val integerClassBType = classBTypeFromInternalName("java/lang/Integer") val lowestOneBitMethod = byteCodeRepository.methodNode(integerClassBType.internalName, "lowestOneBit", "(I)I").get._1 @@ -720,4 +720,21 @@ class InlinerTest extends ClearAfterClass { assertNoInvoke(getSingleMethod(d, "m")) assertNoInvoke(getSingleMethod(c, "m")) } + + @Test + def inlineTraitCastReceiverToSelf(): Unit = { + val code = + """class C { def foo(x: Int) = x } + |trait T { self: C => + | @inline final def f(x: Int) = foo(x) + | def t1 = f(1) + | def t2(t: T) = t.f(2) + |} + """.stripMargin + val List(c, t, tc) = compile(code) + val t1 = getSingleMethod(tc, "t1") + val t2 = getSingleMethod(tc, "t2") + val cast = TypeOp(CHECKCAST, "C") + Set(t1, t2).foreach(m => assert(m.instructions.contains(cast), m.instructions)) + } } |