Skip to content

Commit c0941f3

Browse files
authored
Merge pull request #5423 from dotty-staging/fix-implicit-shortcut-bridge
Fix #5212: Fix bridge generation for implicit shortcuts
2 parents a043541 + 235e38b commit c0941f3

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

compiler/src/dotty/tools/dotc/transform/Bridges.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont
119119
if (!opc.overriding.is(Deferred)) {
120120
addBridgeIfNeeded(opc.overriding, opc.overridden)
121121

122-
if (needsImplicitShortcut(opc.overriding)(ectx))
122+
if (needsImplicitShortcut(opc.overriding)(ectx) && needsImplicitShortcut(opc.overridden)(ectx))
123123
// implicit shortcuts do not show up in the Bridges cursor, since they
124124
// are created only when referenced. Therefore we need to generate a bridge
125125
// for them specifically, if one is needed for the original methods.
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
abstract class A[T] {
2+
def foo: T
3+
}
4+
class B extends A[implicit Int => Int] {
5+
// No bridge needed for foo$direct
6+
def foo: implicit Int => Int = 1
7+
}
8+
9+
abstract class X[T] extends A[implicit T => T] {
10+
def foo: implicit T => T
11+
}
12+
13+
class Y extends X[Int] {
14+
def foo: implicit Int => Int = 1
15+
}
16+
17+
object Test {
18+
def check(expected: Set[String], cls: Class[_]): Unit = {
19+
val actual = cls.getMethods.filter(_.getName.startsWith("foo")).map(_.toString).toSet
20+
assert(expected == actual, s"[$cls] expected: ${expected}\nactual: $actual")
21+
}
22+
23+
def main(args: Array[String]): Unit = {
24+
val expectedB = Set(
25+
"public scala.Function1 B.foo()", // user-written method
26+
"public int B.foo$direct(int)", // shortcut added by ShortcutImplicits
27+
"public java.lang.Object B.foo()" // bridge to A#foo
28+
)
29+
val expectedX = Set(
30+
"public abstract scala.Function1 X.foo()", // user-written method
31+
"public abstract java.lang.Object X.foo$direct(java.lang.Object)", // shortcut
32+
"public abstract java.lang.Object A.foo()" // Inherited from A
33+
)
34+
val expectedY = Set(
35+
"public scala.Function1 Y.foo()", // user-written method
36+
"public java.lang.Object Y.foo()", // Bridge to A#foo
37+
"public int Y.foo$direct(int)", // shortcut
38+
"public java.lang.Object Y.foo$direct(java.lang.Object)", // bridge to X#foo$direct
39+
)
40+
41+
check(expectedB, classOf[B])
42+
check(expectedX, classOf[X[_]])
43+
check(expectedY, classOf[Y])
44+
}
45+
}

0 commit comments

Comments
 (0)