8000 Merge pull request #7035 from eed3si9n/bport/b10812 · scala/scala@4c9780f · GitHub
[go: up one dir, main page]

Skip to content

Commit 4c9780f

Browse files
authored
Merge pull request #7035 from eed3si9n/bport/b10812
Emit bridge method forwarders with BRIDGE flag
2 parents 9a22194 + 0763168 commit 4c9780f

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,12 @@ abstract class BCodeHelpers extends BCodeIdiomatic {
790790
*
791791
* must-single-thread
792792
*/
793-
private def addForwarder(isRemoteClass: Boolean, jclass: asm.ClassVisitor, moduleClass: Symbol, m: Symbol): Unit = {
793+
private def addForwarder(
794+
isRemoteClass: Boolean,
795+
isBridge: Boolean,
796+
jclass: asm.ClassVisitor,
797+
moduleClass: Symbol,
798+
m: Symbol): Unit = {
794799
def staticForwarderGenericSignature: String = {
795800
// scala/bug#3452 Static forwarder generation uses the same erased signature as the method if forwards to.
796801
// By rights, it should use the signature as-seen-from the module class, and add suitable
@@ -814,8 +819,8 @@ abstract class BCodeHelpers extends BCodeIdiomatic {
814819
* and we don't know what classes might be subclassing the companion class. See scala/bug#4827.
815820
*/
816821
// TODO: evaluate the other flags we might be dropping on the floor here.
817-
// TODO: ACC_SYNTHETIC ?
818822
val flags = GenBCode.PublicStatic |
823+
(if (isBridge) asm.Opcodes.ACC_BRIDGE else 0) |
819824
(if (m.isVarargsMethod) asm.Opcodes.ACC_VARARGS else 0) |
820825
(if (m.isDeprecated) asm.Opcodes.ACC_DEPRECATED else 0)
821826

@@ -885,7 +890,11 @@ abstract class BCodeHelpers extends BCodeIdiomatic {
885890
log(s"No forwarder for non-public member $m")
886891
else {
887892
log(s"Adding static forwarder for '$m' from $jclassName to '$moduleClass'")
888-
addForwarder(isRemoteClass, jclass, moduleClass, m)
893+
addForwarder(isRemoteClass,
894+
isBridge = m.isBridge,
895+
jclass,
896+
moduleClass,
897+
m)
889898
}
890899
}
891900
}
@@ -1161,7 +1170,12 @@ object BCodeHelpers {
11611170
val ExcludedForwarderFlags = {
11621171
import scala.tools.nsc.symtab.Flags._
11631172
// Should include DEFERRED but this breaks findMember.
1164-
SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO
1173+
// Note that BRIDGE is *not* excluded. Trying to exclude bridges by flag doesn't work, findMembers
1174+
// will then include the member from the parent (which the bridge overrides / implements).
1175+
// This caused scala/bug#11061 and scala/bug#10812. In 2.13, they are fixed by not emitting
1176+
// forwarders for bridges. But in 2.12 that's not binary compatible, so instead we continue to
1177+
// emit forwarders for bridges, but mark them with ACC_BRIDGE.
1178+
SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | PRIVATE | MACRO
11651179
}
11661180

11671181
/**

test/junit/scala/tools/nsc/backend/jvm/BytecodeTest.scala

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,42 @@ import scala.collection.JavaConverters._
1515
class BytecodeTest extends BytecodeTesting {
1616
import compiler._
1717

18+
@Test
19+
def bridgeFlag(): Unit = {
20+
val code =
21+
""" A { def f: Object = null }
22+
|object B extends A { override def f: String = "b" }
23+
""".stripMargin
24+
for (base <- List("trait", "class")) {
25+
val List(a, bMirror, bModule) = compileClasses(base + code)
26+
assertEquals("B", bMirror.name)
27+
assertEquals(List("f()Ljava/lang/Object;0x49", "f()Ljava/lang/String;0x9"),
28+
bMirror.methods.asScala
29+
.filter(_.name == "f")
30+
.map(m => m.name + m.desc + "0x" + Integer.toHexString(m.access)).toList.sorted)
31+
}
32+
}
33+
34+
@Test
35+
def varArg(): Unit = {
36+
val code =
37+
""" A { @annotation.varargs def f(i: Int*): Object = null }
38+
|object B extends A { @annotation.varargs override def f(i: Int*): String = "b" }
39+
""".stripMargin
40+
for (base <- List("trait", "class")) {
41+
val List(a, bMirror, bModule) = compileClasses(base + code)
42+
assertEquals("B", bMirror.name)
43+
assertEquals(List(
44+
"f(Lscala/collection/Seq;)Ljava/lang/Object;0x49",
45+
"f(Lscala/collection/Seq;)Ljava/lang/String;0x9",
46+
"f([I)Ljava/lang/Object;0xc9",
47+
"f([I)Ljava/lang/String;0x89"),
48+
bMirror.methods.asScala
49+
.filter(_.name == "f")
50+
.map(m => m.name + m.desc + "0x" + Integer.toHexString(m.access)).toList.sorted)
51+
}
52+
}
53+
1854
@Test
1955
def t6288bJumpPosition(): Unit = {
2056
val code =

0 commit comments

Comments
 (0)
0