summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala27
1 files changed, 26 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 19cdcd2590..3712745590 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -1397,13 +1397,38 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
}
clasz.fields foreach genField
- clasz.methods foreach { im => genMethod(im, c.symbol.isInterface) }
+ clasz.methods foreach { im =>
+ if (im.symbol.isBridge && isRedundantBridge(im, clasz))
+ // We can't backport the erasure fix of SI-7120 to 2.10.x, but we can detect and delete
+ // bridge methods with identical signatures to their targets.
+ //
+ // NOTE: this backstop only implemented here in the ASM backend, and is not implemented in the FJBG backend.
+ debugwarn(s"Discarding redundant bridge method: ${im.symbol.debugLocationString}. See SI-8114.")
+ else
+ genMethod(im, c.symbol.isInterface)
+ }
addInnerClasses(clasz.symbol, jclass)
jclass.visitEnd()
writeIfNotTooBig("" + c.symbol.name, thisName, jclass, c.symbol)
}
+ private def isRedundantBridge(bridge: IMethod, owner: IClass): Boolean = {
+ def lastCalledMethod: Option[Symbol] = bridge.code.instructions.reverseIterator.collectFirst {
+ case CALL_METHOD(meth, _) => meth
+ }
+ def hasSameSignatureAsBridge(targetMethod: Symbol): Boolean = {
+ val targetIMethod = clasz.methods find (m => m.symbol == targetMethod)
+ // Important to compare the IMethod#paramss, rather then the erased MethodTypes, as
+ // due to the bug SI-7120, these are out of sync. For example, in the `applyOrElse`
+ // method in run/t8114.scala, the method symbol info has a parameter of type `Long`,
+ // but the IMethod parameter has type `Object`. The latter comes from the info of the
+ // symbol representing the parameter ValDef in the tree, which is incorrectly erased.
+ targetIMethod exists (m => bridge.matchesSignature(m))
+ }
+ lastCalledMethod exists hasSameSignatureAsBridge
+ }
+
/**
* @param owner internal name of the enclosing class of the class.
*