summaryrefslogtreecommitdiff
path: root/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala
blob: 52e19b48fd316773583baab9bfdcb4e27644ad78 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package scala.tools.nsc
package backend.jvm
package opt

import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.Test
import scala.tools.asm.Opcodes._
import org.junit.Assert._

import CodeGenTools._
import scala.tools.partest.ASMConverters
import ASMConverters._
import AsmUtils._

import scala.collection.convert.decorateAsScala._

object InlinerSeparateCompilationTest {
  val args = "-Yopt:l:classpath"
}

@RunWith(classOf[JUnit4])
class InlinerSeparateCompilationTest {
  import InlinerSeparateCompilationTest._

  @Test
  def inlnieMixedinMember(): Unit = {
    val codeA =
      """trait T {
        |  @inline def f = 0
        |}
        |object O extends T {
        |  @inline def g = 1
        |}
      """.stripMargin

    val codeB =
      """class C {
        |  def t1(t: T) = t.f
        |  def t2 = O.f
        |  def t3 = O.g
        |}
      """.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 _))
    assertInvoke(getSingleMethod(c, "t1"), "T", "f")
//    assertNoInvoke(getSingleMethod(c, "t2")) // SD-85
    assertNoInvoke(getSingleMethod(c, "t3"))
  }

  @Test
  def inlineSealedMember(): Unit = {
    val codeA =
      """sealed trait T {
        |  @inline def f = 1
        |}
      """.stripMargin

    val codeB =
      """class C {
        |  def t1(t: T) = t.f
        |}
      """.stripMargin

    val List(c, t) = compileClassesSeparately(List(codeA, codeB), args)
    assertNoInvoke(getSingleMethod(c, "t1"))
  }

  @Test
  def inlineInheritedMember(): Unit = {
    val codeA =
      """trait T {
        |  @inline final def f = 1
        |}
        |trait U extends T {
        |  @inline final def g = f
        |}
      """.stripMargin

    val codeB =
      """class C extends U {
        |  def t1 = this.f
        |  def t2 = this.g
        |  def t3(t: T) = t.f
        |}
      """.stripMargin

    val List(c, t, u) = compileClassesSeparately(List(codeA, codeB), args)
    for (m <- List("t1", "t2", "t3")) assertNoInvoke(getSingleMethod(c, m))
  }

  @Test
  def inlineWithSelfType(): Unit = {
    val assembly =
      """trait Assembly extends T {
        |  @inline final def g = 1
        |  @inline final def n = m
        |}
      """.stripMargin

    val codeA =
      s"""trait T { self: Assembly =>
         |  @inline final def f = g
         |  @inline final def m = 1
         |}
         |$assembly
      """.stripMargin

    val List(a, t) = compileClassesSeparately(List(codeA, assembly), args)
    assertNoInvoke(getSingleMethod(t, "f"))
    assertNoInvoke(getSingleMethod(a, "n"))
  }
}