@@ -324,8 +324,6 @@ class InlinerTest extends ClearAfterClass {
324324 |}
325325 """ .stripMargin
326326 val List (c, t) = compile(code)
327- println(textify(c))
328- println(textify(t))
329327 assertNoInvoke(getSingleMethod(c, " g" ))
330328 }
331329
@@ -507,8 +505,7 @@ class InlinerTest extends ClearAfterClass {
507505 " T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" )
508506 var count = 0
509507 val List (c, t) = compile(code, allowMessage = i => {count += 1 ; warns.exists(i.msg contains _)})
510- // 3rd warnings because of mixin-method, see SD-86
511- assert(count == 3 , count)
508+ assert(count == 2 , count)
512509 assertInvoke(getSingleMethod(c, " t1" ), " T" , " f" )
513510 assertInvoke(getSingleMethod(c, " t2" ), " C" , " f" )
514511 }
@@ -535,27 +532,22 @@ class InlinerTest extends ClearAfterClass {
535532 |}
536533 |object O extends T {
537534 | @inline def g = 1
538- | // mixin generates `def f = T$class.f(this) `, which is inlined here (we get ICONST_0)
535+ | // mixin generates `def f = super[T].f `, which is inlined here (we get ICONST_0)
539536 |}
540537 |class C {
541538 | def t1 = O.f // the mixin method of O is inlined, so we directly get the ICONST_0
542539 | def t2 = O.g // object members are inlined
543540 | def t3(t: T) = t.f // no inlining here
544541 |}
545542 """ .stripMargin
546- val warns = Set (
547- " T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" ,
548- // SD-86 -- once the mixin-method O.f inlines the body of T.f, we can also inline O.g into class C.
549- """ O$::f()I is annotated @inline but could not be inlined:
550- |The callee O$::f()I contains the instruction INVOKESPECIAL T.f ()I
551- |that would cause an IllegalAccessError when inlined into class C""" .stripMargin)
543+ val warn = " T::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden"
552544 var count = 0
553- val List (c, oMirror, oModule, t) = compile(code, allowMessage = i => {count += 1 ; warns.exists( i.msg contains _) })
554- assert(count == 3 , count) // SD-86
545+ val List (c, oMirror, oModule, t) = compile(code, allowMessage = i => {count += 1 ; i.msg contains warn })
546+ assert(count == 1 , count)
555547
556- // assertNoInvoke(getSingleMethod(oModule, "f")) // SD-86
548+ assertNoInvoke(getSingleMethod(oModule, " f" ))
557549
558- // assertNoInvoke(getSingleMethod(c, "t1")) // SD-86
550+ assertNoInvoke(getSingleMethod(c, " t1" ))
559551 assertNoInvoke(getSingleMethod(c, " t2" ))
560552 assertInvoke(getSingleMethod(c, " t3" ), " T" , " f" )
561553 }
@@ -569,12 +561,10 @@ class InlinerTest extends ClearAfterClass {
569561 |}
570562 |trait Assembly extends T {
571563 | @inline final def g = 1
572- | @inline final def n = m // inlined. (*)
573- | // (*) the declaration class of m is T. the signature of T$class.m is m(LAssembly;)I. so we need the self type to build the
574- | // signature. then we can look up the MethodNode of T$class.m and then rewrite the INVOKEINTERFACE to INVOKESTATIC.
564+ | @inline final def n = m // inlined (m is final)
575565 |}
576566 |class C {
577- | def t1(a: Assembly) = a.f // like above, decl class is T, need self-type of T to rewrite the interface call to static.
567+ | def t1(a: Assembly) = a.f // inlined (f is final)
578568 | def t2(a: Assembly) = a.n
579569 |}
580570 """ .stripMargin
@@ -618,30 +608,30 @@ class InlinerTest extends ClearAfterClass {
618608 val code =
619609 """ trait T1 {
620610 | @inline def f: Int = 0
621- | @inline def g1 = f // not inlined: f not final, so T1$class.g1 has an interface call T1.f
611+ | @inline def g1 = f // not inlined: f not final
622612 |}
623613 |
624- |// erased self-type (used in impl class for `self` parameter) : T1
614+ |// erased self-type: T1
625615 |trait T2a { self: T1 with T2a =>
626616 | @inline override final def f = 1
627- | @inline def g2a = f // inlined: resolved as T2a.f, which is re-written to T2a$class.f, so T2a$class.g2a has ICONST_1
617+ | @inline def g2a = f // inlined: resolved as T2a.f
628618 |}
629619 |
630620 |final class Ca extends T1 with T2a {
631- | // mixin generates accessors like `def g1 = T1$class .g1`, the impl class method call is inlined into the accessor.
621+ | // mixin generates accessors like `def g1 = super[T1] .g1`, the impl super call is inlined into the accessor.
632622 |
633623 | def m1a = g1 // call to accessor, inlined, we get the interface call T1.f
634624 | def m2a = g2a // call to accessor, inlined, we get ICONST_1
635625 | def m3a = f // call to accessor, inlined, we get ICONST_1
636626 |
637- | def m4a(t: T1) = t.f // T1.f is not final, so not inlined, interface call to T1.f
638- | def m5a(t: T2a) = t.f // re-written to T2a$class.f, inlined, ICONST_1
627+ | def m4a(t: T1) = t.f // T1.f is not final, so not inlined, we get an interface call T1.f
628+ | def m5a(t: T2a) = t.f // inlined, we get ICONST_1
639629 |}
640630 |
641631 |// erased self-type: T2b
642632 |trait T2b { self: T2b with T1 =>
643633 | @inline override final def f = 1
644- | @inline def g2b = f // not inlined: resolved as T1.f, so T2b$class.g2b has an interface call T1.f
634+ | @inline def g2b = f // not inlined: resolved as T1.f, we get an interface call T1.f
645635 |}
646636 |
647637 |final class Cb extends T1 with T2b {
@@ -650,31 +640,26 @@ class InlinerTest extends ClearAfterClass {
650640 | def m3b = f // inlined, we get ICONST_1
651641 |
652642 | def m4b(t: T1) = t.f // T1.f is not final, so not inlined, interface call to T1.f
653- | def m5b(t: T2b) = t.f // re-written to T2b$class.f, inlined, ICONST_1
643+ | def m5b(t: T2b) = t.f // inlined, ICONST_1
654644 |}
655645 """ .stripMargin
656646
657- val warnings = Set (
658- " T1::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" ,
659- " T2b::g2b()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" ,
660- " T1::g1()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" ,
661- " T2a::g2a()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" ,
662- " T1::g1()I is annotated @inline but cannot be inlined: the method is not final and may be overridden" )
647+ val warning = " T1::f()I is annotated @inline but cannot be inlined: the method is not final and may be overridden"
663648 var count = 0
664- val List (ca, cb, t1, t2a, t2b) = compile(code, allowMessage = i => {count += 1 ; warnings.exists( i.msg contains _) })
665- assert(count == 8 , count) // see comments, f is not inlined 4 times, additional warnings due to SD-86
649+ val List (ca, cb, t1, t2a, t2b) = compile(code, allowMessage = i => {count += 1 ; i.msg contains warning })
650+ assert(count == 4 , count) // see comments, f is not inlined 4 times
666651
667652 assertNoInvoke(getSingleMethod(t2a, " g2a" ))
668653 assertInvoke(getSingleMethod(t2b, " g2b" ), " T1" , " f" )
669654
670- // assertInvoke(getSingleMethod(ca, "m1a"), "T1", "f") // disabled due to SD-86: m1a calls the mixin-method g1a, which calls super[T1].g1a. we inline the mixin-method and end up with the super call.
671- // assertNoInvoke(getSingleMethod(ca, "m2a")) // no invoke, see comment on def g2a // SD-86
655+ assertInvoke(getSingleMethod(ca, " m1a" ), " T1" , " f" )
656+ assertNoInvoke(getSingleMethod(ca, " m2a" )) // no invoke, see comment on def g2a
672657 assertNoInvoke(getSingleMethod(ca, " m3a" ))
673658 assertInvoke(getSingleMethod(ca, " m4a" ), " T1" , " f" )
674659 assertNoInvoke(getSingleMethod(ca, " m5a" ))
675660
676- // assertInvoke(getSingleMethod(cb, "m1b"), "T1", "f") // SD-86
677- // assertInvoke(getSingleMethod(cb, "m2b"), "T1", "f") // invoke, see comment on def g2b // SD-86
661+ assertInvoke(getSingleMethod(cb, " m1b" ), " T1" , " f" )
662+ assertInvoke(getSingleMethod(cb, " m2b" ), " T1" , " f" ) // invoke, see comment on def g2b
678663 assertNoInvoke(getSingleMethod(cb, " m3b" ))
679664 assertInvoke(getSingleMethod(cb, " m4b" ), " T1" , " f" )
680665 assertNoInvoke(getSingleMethod(cb, " m5b" ))
@@ -772,8 +757,8 @@ class InlinerTest extends ClearAfterClass {
772757 | final val d = 3
773758 | final val d1: Int = 3
774759 |
775- | @noinline def f = 5 // re-written to T$class
776- | @noinline final def g = 6 // re-written
760+ | @noinline def f = 5
761+ | @noinline final def g = 6
777762 |
778763 | @noinline def h: Int
779764 | @inline def i: Int
@@ -786,8 +771,8 @@ class InlinerTest extends ClearAfterClass {
786771 | final val d = 3
787772 | final val d1: Int = 3
788773 |
789- | @noinline def f = 5 // not re-written (not final)
790- | @noinline final def g = 6 // re-written
774+ | @noinline def f = 5
775+ | @noinline final def g = 6
791776 |
792777 | @noinline def h: Int
793778 | @inline def i: Int
@@ -1508,4 +1493,14 @@ class InlinerTest extends ClearAfterClass {
15081493 val List (a, b) = compileClassesSeparately(List (codeA, codeB), extraArgs = " -Yopt:l:project -Yopt-warnings" )
15091494 assertInvoke(getSingleMethod(b, " t" ), " A" , " f" )
15101495 }
1496+
1497+ @ Test
1498+ def sd86 (): Unit = {
1499+ val code =
1500+ """ trait T { @inline def f = 1 } // note that f is not final
1501+ |class C extends T
1502+ """ .stripMargin
1503+ val List (c, t) = compile(code, allowMessage = _ => true )
1504+ assertSameSummary(getSingleMethod(c, " f" ), List (ICONST_1 , IRETURN ))
1505+ }
15111506}
0 commit comments