summaryrefslogtreecommitdiff
path: root/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala
blob: 9b1609a1307a09df577384b77c8306d6f38d42dc (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
package scala.tools.nsc
package backend.jvm
package opt

import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

import scala.tools.testing.BytecodeTesting._

@RunWith(classOf[JUnit4])
class InlinerSeparateCompilationTest {
  val args = "-opt:l:classpath"

  @Test
  def inlineMixedinMember(): 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 warn = "T::f()I is annotated @inline but could not be inlined:\nThe method is not final and may be overridden."
    val List(c, o, oMod, t) = compileClassesSeparately(List(codeA, codeB), args + " -opt-warnings", _.msg contains warn)
    assertInvoke(getMethod(c, "t1"), "T", "f")
    assertNoInvoke(getMethod(c, "t2"))
    assertNoInvoke(getMethod(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(getMethod(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(getMethod(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(getMethod(t, "f"))
    assertNoInvoke(getMethod(a, "n"))
  }
}