Skip to content

Commit b851a9f

Browse files
authored
Merge pull request scala#7843 from smarter/static-mf
Emit mixin forwarders as bridges to avoid needing generic signatures
2 parents cc648bf + ab00237 commit b851a9f

File tree

14 files changed

+73
-74
lines changed

14 files changed

+73
-74
lines changed

src/compiler/scala/tools/nsc/transform/Mixin.scala

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -169,33 +169,7 @@ abstract class Mixin extends Transform with ast.TreeDSL with AccessorSynthesis {
169169
clazz.info.decls enter member setFlag MIXEDIN resetFlag JAVA_DEFAULTMETHOD
170170
}
171171
def cloneAndAddMember(mixinClass: Symbol, mixinMember: Symbol, clazz: Symbol): Symbol =
172-
addMember(clazz, cloneBeforeErasure(mixinClass, mixinMember, clazz))
173-
174-
def cloneBeforeErasure(mixinClass: Symbol, mixinMember: Symbol, clazz: Symbol): Symbol = {
175-
val newSym = enteringErasure {
176-
// since we used `mixinMember` from the interface that represents the trait that's
177-
// being mixed in, have to instantiate the interface type params (that may occur in mixinMember's
178-
// info) as they are seen from the class. We can't use the member that we get from the
179-
// implementation class, as it's a clone that was made after erasure, and thus it does not
180-
// know its info at the beginning of erasure anymore.
181-
val sym = mixinMember cloneSymbol clazz
182-
183-
val erasureMap = erasure.erasure(mixinMember)
184-
val erasedInterfaceInfo: Type = erasureMap(mixinMember.info)
185-
val specificForwardInfo = (clazz.thisType baseType mixinClass) memberInfo mixinMember
186-
val forwarderInfo =
187-
if (erasureMap(specificForwardInfo) =:= erasedInterfaceInfo)
188-
specificForwardInfo
189-
else {
190-
erasedInterfaceInfo
191-
}
192-
// Optimize: no need if mixinClass has no typeparams.
193-
// !!! JZ Really? What about the effect of abstract types, prefix?
194-
if (mixinClass.typeParams.isEmpty) sym
195-
else sym modifyInfo (_ => forwarderInfo)
196-
}
197-
newSym
198-
}
172+
addMember(clazz, mixinMember.cloneSymbol(clazz).setFlag(BRIDGE))
199173

200174
def publicizeTraitMethods(clazz: Symbol): Unit = {
201175
if (treatedClassInfos(clazz) != clazz.info) {

test/files/neg/t4749.check

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ t4749.scala:28: warning: Fail6 has a valid main method (args: Array[String])Unit
3737

3838
object Fail6 {
3939
^
40-
t4749.scala:44: warning: not a valid main method for bippy.Win3,
41-
because main methods must have the exact signature (Array[String])Unit.
40+
t4749.scala:42: warning: not a valid main method for bippy.Win3,
41+
because main methods cannot refer to type parameters or abstract types.
4242
To define an entry point, please define the main method as:
4343
def main(args: Array[String]): Unit
4444

45-
object Win3 extends WinBippy[Unit] { }
46-
^
45+
def main(args: Array[String]): T = null.asInstanceOf[T]
46+
^
4747
error: No warnings can be incurred under -Xfatal-warnings.
4848
7 warnings found
4949
one error found

test/files/neg/t5148.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
t5148.scala:4: error: Symbol 'term scala.tools.nsc.interpreter.IMain.memberHandlers' is missing from the classpath.
1+
t5148.scala:4: error: Symbol 'type scala.tools.nsc.interpreter.IMain.Request' is missing from the classpath.
22
This symbol is required by 'method scala.tools.nsc.interpreter.Imports.allReqAndHandlers'.
3-
Make sure that term memberHandlers is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
3+
Make sure that type Request is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
44
A full rebuild may help if 'Imports.class' was compiled against an incompatible version of scala.tools.nsc.interpreter.IMain.
55
class IMain extends Imports
66
^

test/files/run/mixin-bridge-methods.scala

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Foo(0)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
case class Foo(x: Int)
2+
3+
trait A[X] {
4+
def concat[Dummy](suffix: Int): Dummy = ???
5+
}
6+
7+
class Bar extends A[Foo] {
8+
def concat(suffix: Int): Foo = Foo(0)
9+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class Test {
2+
public static void main(String[] args) {
3+
Bar bar = new Bar();
4+
Foo x = bar.concat(0);
5+
System.out.println(x);
6+
}
7+
}

test/files/run/mixin-signatures.check

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
class Test$bar1$ {
2-
public java.lang.String Test$bar1$.f(java.lang.Object)
32
public java.lang.Object Test$bar1$.f(java.lang.Object) <bridge> <synthetic>
3+
public java.lang.String Test$bar1$.f(java.lang.Object) <bridge> <synthetic>
44
public java.lang.String Test$bar1$.g(java.lang.String)
55
public java.lang.Object Test$bar1$.g(java.lang.Object) <bridge> <synthetic>
66
public java.lang.String Test$bar1$.g(java.lang.Object) <bridge> <synthetic>
7-
public java.lang.Object Test$bar1$.h(java.lang.Object)
7+
public java.lang.Object Test$bar1$.h(java.lang.Object) <bridge> <synthetic>
88
}
99

1010
class Test$bar2$ {
11-
public java.lang.Object Test$bar2$.f(java.lang.String)
1211
public java.lang.Object Test$bar2$.f(java.lang.Object) <bridge> <synthetic>
12+
public java.lang.Object Test$bar2$.f(java.lang.String) <bridge> <synthetic>
1313
public java.lang.String Test$bar2$.g(java.lang.String)
1414
public java.lang.Object Test$bar2$.g(java.lang.Object) <bridge> <synthetic>
1515
public java.lang.Object Test$bar2$.g(java.lang.String) <bridge> <synthetic>
16-
public java.lang.Object Test$bar2$.h(java.lang.Object)
16+
public java.lang.Object Test$bar2$.h(java.lang.Object) <bridge> <synthetic>
1717
}
1818

1919
class Test$bar3$ {
@@ -23,7 +23,7 @@ class Test$bar3$ {
2323
public java.lang.String Test$bar3$.g(java.lang.String)
2424
public java.lang.Object Test$bar3$.g(java.lang.Object) <bridge> <synthetic>
2525
public java.lang.String Test$bar3$.g(java.lang.Object) <bridge> <synthetic>
26-
public java.lang.Object Foo3.h(java.lang.Object)
26+
public java.lang.Object Foo3.h(java.lang.Object) <bridge> <synthetic>
2727
}
2828

2929
class Test$bar4$ {
@@ -33,7 +33,7 @@ class Test$bar4$ {
3333
public java.lang.String Test$bar4$.g(java.lang.String)
3434
public java.lang.Object Test$bar4$.g(java.lang.Object) <bridge> <synthetic>
3535
public java.lang.Object Test$bar4$.g(java.lang.String) <bridge> <synthetic>
36-
public java.lang.Object Foo4.h(java.lang.Object)
36+
public java.lang.Object Foo4.h(java.lang.Object) <bridge> <synthetic>
3737
}
3838

3939
class Test$bar5$ {
@@ -45,7 +45,7 @@ class Test$bar5$ {
4545
public java.lang.Object Test$bar5$.g(java.lang.Object) <bridge> <synthetic>
4646
public java.lang.Object Test$bar5$.g(java.lang.String) <bridge> <synthetic>
4747
public java.lang.String Test$bar5$.g(java.lang.Object) <bridge> <synthetic>
48-
public java.lang.Object Test$bar5$.h(java.lang.Object)
48+
public java.lang.Object Test$bar5$.h(java.lang.Object) <bridge> <synthetic>
4949
}
5050

5151
interface Foo1 {

test/files/run/t3452d/Test.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
1-
import scala.collection.immutable.Nil;
2-
import scala.collection.immutable.List;
3-
41
public class Test {
52
public static void main(String[] args) {
63
C<String> c = new C<String>();
7-
// TODO add a bridge during mixin so we can expose
8-
// sharper generic signature for `tail`.
9-
/*Traversable<String>*/ Object ls = c.tail();
4+
scala.collection.Iterable<String> ls = c.tail();
105
}
116
}

test/files/run/t3452g/A.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ trait TraversableLike[A, Repr] {
44

55
abstract class AbstractTrav[A] extends TraversableLike[A, AbstractTrav[A]]
66

7+
class C1 extends AbstractTrav[String]
8+
79
object O extends AbstractTrav[String]
810

9-
class C[A] extends AbstractTrav[A]
11+
class C2[A] extends AbstractTrav[A]

test/files/run/t3452g/Test.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
21
public class Test {
3-
public static void main(String[] args) {
4-
// To get better types here, we would need to
5-
// add bridge during mixin so we can expose
6-
// a generic return type of Traversable<A>, because the erasure
7-
// of this (Traversable) differs from the erasure of the mixed
8-
// method (erasure(Repr) = Object)
2+
public static void main(String[] args) {
3+
AbstractTrav<String> lsSharp1 = new C1().tail();
94

10-
Object lsSharp = O.tail();
5+
// Object is the result type for the static forwarder (might be because of #11305)
6+
Object lsSharp2 = O.tail();
117

12-
Object lsSharp2 = new C<String>().tail();
13-
}
8+
AbstractTrav<String> lsSharp3 = new C2<String>().tail();
9+
}
1410
}

test/files/run/t7932.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
public Category<?> C.category()
2-
public Category<scala.Tuple2> C.category1()
1+
public Category C.category()
2+
public Category C.category1()
33
public default Category<java.lang.Object> M1.category()
44
public default Category<scala.Tuple2> M1.category1()
55
public static Category M1.category$(M1)
66
public static Category M1.category1$(M1)
77
public default Category<java.lang.Object> M2.category()
88
public default Category<scala.Tuple2> M2.category1()
99
public static Category M2.category$(M2)
10-
public static Category M2.category1$(M2)
10+
public static Category M2.category1$(M2)

test/files/run/t8905/DoubleRDD.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import java.util.Comparator
2+
3+
trait RDDLike[T] {
4+
def max(comp: Comparator[T]): T = {
5+
(1.0).asInstanceOf[T]
6+
}
7+
}
8+
9+
class DoubleRDD extends RDDLike[java.lang.Double] { }

test/files/run/t8905/Test.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import java.util.Comparator;
2+
3+
public class Test {
4+
private static class DoubleComparator implements Comparator<Double> {
5+
public int compare(Double o1, Double o2) {
6+
return o1.compareTo(o2);
7+
}
8+
}
9+
10+
public static void main(String[] args) {
11+
DoubleRDD rdd = new DoubleRDD();
12+
RDDLike<Double> rddLike = rdd;
13+
14+
// This call works fine:
15+
double rddLikeMax = rddLike.max(new DoubleComparator());
16+
// In Scala 2.10.4, this code compiles but this call fails at runtime:
17+
// java.lang.NoSuchMethodError: DoubleRDD.max(Ljava/util/Comparator;)Ljava/lang/Double;
18+
double rddMax = rdd.max(new DoubleComparator());
19+
}
20+
}

0 commit comments

Comments
 (0)