Skip to content

Commit 3f37c5a

Browse files
committed
No mixin forwarders for known binary incompatible trait overrides
New overrides added to traits are not forwards binary compatible (scala/bug#12137). For those overrides that were added since 2.12.0, a new special case in Mixin avoids generating the mixin forwarder, so compiling with 2.12.13 will emit code that is binary compatible with 2.12.0. Tested with this code: ``` object A extends scala.math.Ordering.IntOrdering // `reverse` override was added object B extends scala.math.Ordering.FloatOrdering // `reverse` override was removed object Test { def main(args: Array[String]): Unit = { println(A.reverse) println(B.reverse) } } ``` Code compiled with 2.12.13 (qsc/qs) works with all 2.12 libraries thanks to this fix. ``` qsc Test.scala && sv 2.12.0 Test && sv 2.12.12 Test && qs Test ``` Code compiled with 2.12.0 fails on 2.12.12. The super call in the generated mixin forwarder `B.reverse` invokes the static method `FloatOrdering.reverse$` that no longer exists. This will be the same in 2.12.13. ``` scv 2.12.0 Test.scala && sv 2.12.12 Test java.lang.NoSuchMethodError: scala.math.Ordering$FloatOrdering.reverse$ ```
1 parent 7577c7a commit 3f37c5a

File tree

1 file changed

+27
-1
lines changed

1 file changed

+27
-1
lines changed

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,32 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL with AccessorSynthes
2929
/** The name of the phase: */
3030
val phaseName: String = "mixin"
3131

32+
// See https://github.com/scala/bug/issues/12137#issuecomment-695944076
33+
lazy val binaryIncompatibleTraitOverrides: Set[Symbol] = {
34+
def meth(path: List[String], cls: Symbol): Symbol = path match {
35+
case m :: Nil => cls.map(_.info.member(TermName(m)))
36+
case i :: xs => meth(xs, cls.map(_.info.member(TypeName(i))))
37+
}
38+
// Trait overrides that were added, list from https://github.com/scala/scala/pull/9260/files
39+
// `FloatOrdering.reverse` and `DoubleOrdering.reverse` are trait overrides that were removed (not added)
40+
// in 44318c8959, so there's nothing we can do. Compiling with 2.12.0 and running on 2.12.12 is not binary
41+
// compatible for super calls to these two methods.
42+
enteringTyper{
43+
Set(
44+
List("scala.math.Ordering.IntOrdering", "reverse"),
45+
List("scala.collection.IndexedSeqOptimized", "toList"),
46+
List("scala.collection.LinearSeqOptimized", "tails"),
47+
List("scala.collection.TraversableViewLike", "Transformed", "last"),
48+
List("scala.collection.immutable.SortedSet", "equals"),
49+
List("scala.collection.immutable.SortedMap", "equals"),
50+
List("scala.math.Ordering.OptionOrdering", "equals"),
51+
List("scala.math.Ordering.OptionOrdering", "hashCode"),
52+
).map({
53+
case c :: xs => meth(xs, rootMirror.getClassIfDefined(c))
54+
}).filterNot(_ == NoSymbol)
55+
}
56+
}
57+
3258
/** Some trait methods need to be implemented in subclasses, so they cannot be private.
3359
*
3460
* We used to publicize during explicitouter (for some reason), so the condition is a bit more involved now it's done here
@@ -283,7 +309,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL with AccessorSynthes
283309

284310
if (existsCompetingMethod(clazz.baseClasses) || generateJUnitForwarder || generateSerializationForwarder)
285311
genForwarder(required = true)
286-
else if (settings.mixinForwarderChoices.isTruthy)
312+
else if (settings.mixinForwarderChoices.isTruthy && !binaryIncompatibleTraitOverrides(member))
287313
genForwarder(required = false)
288314
}
289315

0 commit comments

Comments
 (0)