Skip to content

Commit

Permalink
Merge pull request #10410 from som-snytt/tweak/inliner-message
Browse files Browse the repository at this point in the history
Tweak inliner error message
  • Loading branch information
som-snytt committed Jun 23, 2023
2 parents 7992103 + 8b878ec commit ff6bee5
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 49 deletions.
10 changes: 6 additions & 4 deletions src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,14 @@ object BackendReporting {
s"\nthat would cause an IllegalAccessError when inlined into class $callsiteClass."

case IllegalAccessCheckFailed(_, _, _, _, callsiteClass, instruction, cause) =>
s"Failed to check if $calleeMethodSig can be safely inlined to $callsiteClass without causing an IllegalAccessError. Checking instruction ${AsmUtils.textify(instruction)} failed:\n" + cause
sm"""|Failed to check if $calleeMethodSig can be safely inlined to $callsiteClass without causing an IllegalAccessError.
|Checking failed for instruction ${AsmUtils.textify(instruction)}:
|$cause"""

case MethodWithHandlerCalledOnNonEmptyStack(_, _, _, _, callsiteClass, callsiteName, callsiteDesc) =>
s"""The operand stack at the callsite in ${BackendReporting.methodSignature(callsiteClass, callsiteName, callsiteDesc)} contains more values than the
|arguments expected by the callee $calleeMethodSig. These values would be discarded
|when entering an exception handler declared in the inlined method.""".stripMargin
sm"""|The operand stack at the callsite in ${BackendReporting.methodSignature(callsiteClass, callsiteName, callsiteDesc)} contains more values than the
|arguments expected by the callee $calleeMethodSig. These values would be discarded
|when entering an exception handler declared in the inlined method."""

case SynchronizedMethod(_, _, _, _) =>
s"Method $calleeMethodSig cannot be inlined because it is synchronized."
Expand Down
5 changes: 3 additions & 2 deletions test/files/run/noInlineUnknownIndy.check
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
newSource1.scala:1: warning: A_1::test()Ljava/lang/String; could not be inlined:
Failed to check if A_1::test()Ljava/lang/String; can be safely inlined to T without causing an IllegalAccessError. Checking instruction INVOKEDYNAMIC m()LA_1$Fun; [
Failed to check if A_1::test()Ljava/lang/String; can be safely inlined to T without causing an IllegalAccessError.
Checking failed for instruction INVOKEDYNAMIC m()LA_1$Fun; [
// handle kind 0x6 : INVOKESTATIC
not/java/lang/SomeLambdaMetafactory.notAMetaFactoryMethod(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
// arguments:
(Ljava/lang/String;)Ljava/lang/String;,
// handle kind 0x6 : INVOKESTATIC
A_1.lambda$test$0(Ljava/lang/String;)Ljava/lang/String;,
(Ljava/lang/String;)Ljava/lang/String;
] failed:
]:
The callee contains an InvokeDynamic instruction with an unknown bootstrap method (not a LambdaMetaFactory).
class T { def foo = A_1.test }
^
57 changes: 29 additions & 28 deletions test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package scala.tools.nsc
package backend.jvm
package opt

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

import scala.tools.testkit.BytecodeTesting
import scala.tools.testkit.BytecodeTesting._
import scala.collection.mutable
import scala.tools.testkit.BytecodeTesting, BytecodeTesting._

@RunWith(classOf[JUnit4])
class InlineWarningTest extends BytecodeTesting {
Expand Down Expand Up @@ -170,37 +171,37 @@ class InlineWarningTest extends BytecodeTesting {
}

@Test // scala-dev#20
def mixedCompilationSpuriousWarning(): Unit = {
def mixedCompilationSpuriousWarning: Unit = {
val jCode =
"""public class A {
| public static final int bar() { return 100; }
| public final int baz() { return 100; }
|}
""".stripMargin
sm"""|public class A {
| public static final int bar() { return 100; }
| public final int baz() { return 100; }
|}
"""

val sCode =
"""class C {
| @inline final def foo = A.bar()
| @inline final def fii(a: A) = a.baz()
| def t = foo + fii(new A)
|}
""".stripMargin
sm"""|class C {
| @inline final def foo = A.bar()
| @inline final def fii(a: A) = a.baz()
| def t = foo + fii(new A)
|}
"""

val warns = List(
"""C::foo()I is annotated @inline but could not be inlined:
|Failed to check if C::foo()I can be safely inlined to C without causing an IllegalAccessError. Checking instruction INVOKESTATIC A.bar ()I failed:
|The method bar()I could not be found in the class A or any of its parents.
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin,

"""C::fii(LA;)I is annotated @inline but could not be inlined:
|Failed to check if C::fii(LA;)I can be safely inlined to C without causing an IllegalAccessError. Checking instruction INVOKEVIRTUAL A.baz ()I failed:
|The method baz()I could not be found in the class A or any of its parents.
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin
sm"""|C::foo()I is annotated @inline but could not be inlined:
|Failed to check if C::foo()I can be safely inlined to C without causing an IllegalAccessError.
|Checking failed for instruction INVOKESTATIC A.bar ()I:
|The method bar()I could not be found in the class A or any of its parents.
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""",

sm"""|C::fii(LA;)I is annotated @inline but could not be inlined:
|Failed to check if C::fii(LA;)I can be safely inlined to C without causing an IllegalAccessError.
|Checking failed for instruction INVOKEVIRTUAL A.baz ()I:
|The method baz()I could not be found in the class A or any of its parents.
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""",
)
var c = 0
compileClasses(sCode, javaCode = List((jCode, "A.java")), allowMessage = i => { c += 1;
warns.exists(i.msg.contains)
})
assert(c == 2)
val allowed = mutable.Set.from(warns)
compileClasses(sCode, javaCode = List(jCode -> "A.java"), allowMessage = i => allowed.remove(i.msg))
assertTrue(s"${allowed.size} unseen warnings:\n$allowed", allowed.isEmpty)
}
}
31 changes: 16 additions & 15 deletions test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -398,27 +398,28 @@ class InlinerTest extends BytecodeTesting {
// A, so `flop` cannot be inlined, we cannot check if it's safe.

val javaCode =
"""public class A {
| public static final int bar() { return 100; }
|}
""".stripMargin
sm"""|public class A {
| public static final int bar() { return 100; }
|}
"""

val scalaCode =
"""class B {
| @inline final def flop = A.bar
| def g = flop
|}
""".stripMargin
sm"""|class B {
| @inline final def flop = A.bar
| def g = flop
|}
"""

val warn =
"""B::flop()I is annotated @inline but could not be inlined:
|Failed to check if B::flop()I can be safely inlined to B without causing an IllegalAccessError. Checking instruction INVOKESTATIC A.bar ()I failed:
|The method bar()I could not be found in the class A or any of its parents.
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin
sm"""|B::flop()I is annotated @inline but could not be inlined:
|Failed to check if B::flop()I can be safely inlined to B without causing an IllegalAccessError.
|Checking failed for instruction INVOKESTATIC A.bar ()I:
|The method bar()I could not be found in the class A or any of its parents.
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available."""

var c = 0
val b = compileClass(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; i.msg contains warn})
assert(c == 1, c)
val b = compileClass(scalaCode, List(javaCode -> "A.java"), allowMessage = i => { c += 1; i.msg.contains(warn) })
assertEquals(1, c)
val ins = getInstructions(b, "g")
val invokeFlop = Invoke(INVOKEVIRTUAL, "B", "flop", "()I", false)
assert(ins contains invokeFlop, ins.stringLines)
Expand Down

0 comments on commit ff6bee5

Please sign in to comment.