Skip to content

Commit cdafcc2

Browse files
authored
Merge pull request #12860 from dotty-staging/static-forwarder-bridge
Hide problematic static forwarders
2 parents af3703b + 0ed163e commit cdafcc2

File tree

5 files changed

+113
-3
lines changed

5 files changed

+113
-3
lines changed

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import dotty.tools.dotc.core.Names.Name
2121
import dotty.tools.dotc.core.NameKinds.ExpandedName
2222
import dotty.tools.dotc.core.Signature
2323
import dotty.tools.dotc.core.StdNames._
24+
import dotty.tools.dotc.core.NameKinds
2425
import dotty.tools.dotc.core.Symbols._
2526
import dotty.tools.dotc.core.Types
2627
import dotty.tools.dotc.core.Types._
@@ -507,7 +508,7 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
507508
*
508509
* must-single-thread
509510
*/
510-
private def addForwarder(jclass: asm.ClassVisitor, module: Symbol, m: Symbol): Unit = {
511+
private def addForwarder(jclass: asm.ClassVisitor, module: Symbol, m: Symbol, isSynthetic: Boolean): Unit = {
511512
val moduleName = internalName(module)
512513
val methodInfo = module.thisType.memberInfo(m)
513514
val paramJavaTypes: List[BType] = methodInfo.firstParamTypes map toTypeKind
@@ -518,9 +519,10 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
518519
* and we don't know what classes might be subclassing the companion class. See SI-4827.
519520
*/
520521
// TODO: evaluate the other flags we might be dropping on the floor here.
521-
// TODO: ACC_SYNTHETIC ?
522522
val flags = GenBCodeOps.PublicStatic | (
523523
if (m.is(JavaVarargs)) asm.Opcodes.ACC_VARARGS else 0
524+
) | (
525+
if (isSynthetic) asm.Opcodes.ACC_SYNTHETIC else 0
524526
)
525527

526528
// TODO needed? for(ann <- m.annotations) { ann.symbol.initialize }
@@ -595,7 +597,16 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
595597
report.log(s"No forwarder for non-public member $m")
596598
else {
597599
report.log(s"Adding static forwarder for '$m' from $jclassName to '$moduleClass'")
598-
addForwarder(jclass, moduleClass, m)
600+
// It would be simpler to not generate forwarders for these methods,
601+
// but that wouldn't be binary-compatible with Scala 3.0.0, so instead
602+
// we generate ACC_SYNTHETIC forwarders so Java compilers ignore them.
603+
val isSynthetic =
604+
m0.name.is(NameKinds.SyntheticSetterName) ||
605+
// Only hide bridges generated at Erasure, mixin forwarders are also
606+
// marked as bridge but shouldn't be hidden since they don't have a
607+
// non-bridge overload.
608+
m0.is(Bridge) && m0.initial.validFor.firstPhaseId == erasurePhase.next.id
609+
addForwarder(jclass, moduleClass, m, isSynthetic)
599610
}
600611
}
601612
}

compiler/test/dotc/run-test-pickling.blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ typeclass-derivation3.scala
3434
varargs-abstract
3535
zero-arity-case-class.scala
3636
i12194.scala
37+
i12753

tests/run/i12753.check

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
1
2+
Dbr
3+
1
4+
1
5+
2
6+
1
7+
1
8+
1
9+
1
10+
2
11+
1
12+
1
13+
synthetic public static C D.foo(int)
14+
public static D D.foo(int)
15+
public static D D.t()
16+
synthetic public static java.lang.Object D.bar()
17+
public static java.lang.String D.bar()
18+
public static int O.a()
19+
public static int O.b()
20+
public static int O.c()
21+
public static int O.d()
22+
public static int O.i()
23+
public static int O.j()
24+
public static int O.k()
25+
public static int O.l()
26+
synthetic public static void O.T$_setter_$a_$eq(int)
27+
public static void O.b_$eq(int)
28+
public static void O.j_$eq(int)

tests/run/i12753/C.scala

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
trait C[This <: C[This]]
2+
3+
trait COps[This <: C[This]] {
4+
def t: This
5+
def foo(x: Int): This = t
6+
def bar: Object = "Cbr"
7+
}
8+
9+
class D extends C[D] {
10+
def x = 1
11+
}
12+
object D extends COps[D] {
13+
def t = new D
14+
override def foo(x: Int): D = super.foo(x)
15+
override def bar: String = "Dbr"
16+
}
17+
18+
trait T {
19+
val a = 1
20+
var b = 1
21+
lazy val c = 1
22+
def d = 1
23+
24+
val i: Int
25+
var j: Int
26+
lazy val k: Int = 1
27+
def l: Int
28+
}
29+
object O extends T {
30+
val i: Int = 1
31+
var j: Int = 1
32+
override lazy val k: Int = 1
33+
def l: Int = 1
34+
}

tests/run/i12753/Test.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
public class Test {
2+
public static void s(Object s) {
3+
System.out.println(s);
4+
}
5+
6+
public static void statics(Class<?> c) {
7+
java.lang.reflect.Method[] ms = c.getDeclaredMethods();
8+
java.util.Arrays.sort(ms, (a, b) -> a.toString().compareTo(b.toString()));
9+
for (java.lang.reflect.Method a : ms) {
10+
if (java.lang.reflect.Modifier.isStatic(a.getModifiers()))
11+
s((a.isSynthetic() ? "synthetic " : "") + a);
12+
}
13+
}
14+
15+
public static void main(String[] args) {
16+
s(D.foo(1).x());
17+
s(D.bar().trim());
18+
19+
s(O.a());
20+
s(O.b());
21+
O.b_$eq(2);
22+
s(O.b());
23+
s(O.c());
24+
s(O.d());
25+
26+
s(O.i());
27+
s(O.j());
28+
O.j_$eq(2);
29+
s(O.j());
30+
s(O.k());
31+
s(O.l());
32+
33+
statics(D.class);
34+
statics(O.class);
35+
}
36+
}

0 commit comments

Comments
 (0)