Skip to content

Commit 4b77734

Browse files
authored
Merge pull request scala#5291 from lrytz/sd20
SD-20 Inlcude static methods in the InlineInfo in mixed compilation Fixes scala/scala-dev#20
2 parents 3e0b2c2 + 2c2fd4f commit 4b77734

File tree

6 files changed

+67
-10
lines changed

6 files changed

+67
-10
lines changed

src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,8 +1155,7 @@ object BTypes {
11551155
final case class InlineInfo(isEffectivelyFinal: Boolean,
11561156
sam: Option[String],
11571157
methodInfos: Map[String, MethodInlineInfo],
1158-
warning: Option[ClassInlineInfoWarning]) {
1159-
}
1158+
warning: Option[ClassInlineInfoWarning])
11601159

11611160
val EmptyInlineInfo = InlineInfo(false, None, Map.empty, None)
11621161

src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,9 +562,16 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
562562

563563
var warning = Option.empty[ClassSymbolInfoFailureSI9111]
564564

565+
def keepMember(sym: Symbol) = sym.isMethod && !scalaPrimitives.isPrimitive(sym)
566+
val classMethods = classSym.info.decls.iterator.filter(keepMember)
567+
val methods = if (!classSym.isJavaDefined) classMethods else {
568+
val staticMethods = classSym.companionModule.info.decls.iterator.filter(m => !m.isConstructor && keepMember(m))
569+
staticMethods ++ classMethods
570+
}
571+
565572
// Primitive methods cannot be inlined, so there's no point in building a MethodInlineInfo. Also, some
566573
// primitive methods (e.g., `isInstanceOf`) have non-erased types, which confuses [[typeToBType]].
567-
val methodInlineInfos = classSym.info.decls.iterator.filter(m => m.isMethod && !scalaPrimitives.isPrimitive(m)).flatMap({
574+
val methodInlineInfos = methods.flatMap({
568575
case methodSym =>
569576
if (completeSilentlyAndCheckErroneous(methodSym)) {
570577
// Happens due to SI-9111. Just don't provide any MethodInlineInfo for that method, we don't need fail the compiler.

src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ object BackendReporting {
9696
val missingClassWarning = missingClass match {
9797
case None => ""
9898
case Some(c) =>
99-
if (c.definedInJavaSource) s"\nNote that the parent class ${c.internalName} is defined in a Java source (mixed compilation), no bytecode is available."
100-
else s"\nNote that the parent class ${c.internalName} could not be found on the classpath."
99+
if (c.definedInJavaSource) s"\nNote that class ${c.internalName} is defined in a Java source (mixed compilation), no bytecode is available."
100+
else s"\nNote that class ${c.internalName} could not be found on the classpath."
101101
}
102102
s"The method $name$descriptor could not be found in the class $ownerInternalName or any of its parents." + missingClassWarning
103103

test/junit/scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@ package scala.tools.nsc
22
package backend.jvm
33
package opt
44

5+
import org.junit.Assert._
56
import org.junit.Test
67
import org.junit.runner.RunWith
78
import org.junit.runners.JUnit4
89

910
import scala.collection.JavaConverters._
1011
import scala.collection.generic.Clearable
12+
import scala.tools.nsc.backend.jvm.BTypes.MethodInlineInfo
1113
import scala.tools.nsc.backend.jvm.BackendReporting._
1214
import scala.tools.testing.BytecodeTesting
1315

1416
@RunWith(classOf[JUnit4])
1517
class InlineInfoTest extends BytecodeTesting {
16-
import compiler.global
18+
import compiler._
1719
import global.genBCode.bTypes
1820

1921
override def compilerArgs = "-opt:l:classpath"
@@ -59,4 +61,20 @@ class InlineInfoTest extends BytecodeTesting {
5961

6062
assert(fromSyms == fromAttrs)
6163
}
64+
65+
@Test // scala-dev#20
66+
def javaStaticMethodsInlineInfoInMixedCompilation(): Unit = {
67+
val jCode =
68+
"""public class A {
69+
| public static final int bar() { return 100; }
70+
| public final int baz() { return 100; }
71+
|}
72+
""".stripMargin
73+
compileClasses("class C { new A }", javaCode = List((jCode, "A.java")))
74+
val info = global.genBCode.bTypes.classBTypeFromInternalName("A").info.get.inlineInfo
75+
assertEquals(info.methodInfos, Map(
76+
"bar()I" -> MethodInlineInfo(true,false,false),
77+
"<init>()V" -> MethodInlineInfo(false,false,false),
78+
"baz()I" -> MethodInlineInfo(true,false,false)))
79+
}
6280
}

test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ class InlineWarningTest extends BytecodeTesting {
7575
val warns = List(
7676
"""failed to determine if bar should be inlined:
7777
|The method bar()I could not be found in the class A or any of its parents.
78-
|Note that the parent class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin,
78+
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin,
7979

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

8585
var c = 0
8686
val List(b) = compileToBytes(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.tail.exists(i.msg contains _)})
@@ -168,4 +168,37 @@ class InlineWarningTest extends BytecodeTesting {
168168
compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn })
169169
assert(c == 1, c)
170170
}
171+
172+
@Test // scala-dev#20
173+
def mixedCompilationSpuriousWarning(): Unit = {
174+
val jCode =
175+
"""public class A {
176+
| public static final int bar() { return 100; }
177+
| public final int baz() { return 100; }
178+
|}
179+
""".stripMargin
180+
181+
val sCode =
182+
"""class C {
183+
| @inline final def foo = A.bar()
184+
| @inline final def fii(a: A) = a.baz()
185+
| def t = foo + fii(new A)
186+
|}
187+
""".stripMargin
188+
189+
val warns = List(
190+
"""C::foo()I is annotated @inline but could not be inlined:
191+
|Failed to check if C::foo()I can be safely inlined to C without causing an IllegalAccessError. Checking instruction INVOKESTATIC A.bar ()I failed:
192+
|The method bar()I could not be found in the class A or any of its parents.
193+
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin,
194+
195+
"""C::fii(LA;)I is annotated @inline but could not be inlined:
196+
|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:
197+
|The method baz()I could not be found in the class A or any of its parents.
198+
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin
199+
)
200+
var c = 0
201+
compileClasses(sCode, javaCode = List((jCode, "A.java")), allowMessage = i => { c += 1; warns.exists(i.msg.contains)})
202+
assert(c == 2)
203+
}
171204
}

test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ class InlinerTest extends BytecodeTesting {
416416
"""B::flop()I is annotated @inline but could not be inlined:
417417
|Failed to check if B::flop()I can be safely inlined to B without causing an IllegalAccessError. Checking instruction INVOKESTATIC A.bar ()I failed:
418418
|The method bar()I could not be found in the class A or any of its parents.
419-
|Note that the parent class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin
419+
|Note that class A is defined in a Java source (mixed compilation), no bytecode is available.""".stripMargin
420420

421421
var c = 0
422422
val List(b) = compile(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; i.msg contains warn})
@@ -819,7 +819,7 @@ class InlinerTest extends BytecodeTesting {
819819
val warn =
820820
"""failed to determine if <init> should be inlined:
821821
|The method <init>()V could not be found in the class A$Inner or any of its parents.
822-
|Note that the parent class A$Inner could not be found on the classpath.""".stripMargin
822+
|Note that class A$Inner could not be found on the classpath.""".stripMargin
823823

824824
var c = 0
825825

0 commit comments

Comments
 (0)