diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-01-09 13:58:09 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-01-09 14:16:03 +0100 |
commit | 5876e8c62130b4089b146d4fea5bcd926e47bf6f (patch) | |
tree | c266a266987656f3165daab6ba67be9c1f437449 /src | |
parent | 1f2cd7e5120bb22b14ad81adf8fb09caa5af2853 (diff) | |
download | scala-5876e8c62130b4089b146d4fea5bcd926e47bf6f.tar.gz scala-5876e8c62130b4089b146d4fea5bcd926e47bf6f.tar.bz2 scala-5876e8c62130b4089b146d4fea5bcd926e47bf6f.zip |
[nomaster] SI-8114 Binary compat. workaround for erasure bug SI-7120
We can't backport SI-7120 to 2.10.x as it changes erased signatures,
which can lead to interop problems between 2.10.3 and 2.10.4.
But, we can detect one of the nasty symptoms -- a bridge method
with the same signature as its target -- and treat that.
This commit detects duplicate bridges in the ASM (only) backend
and removes them.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala | 27 |
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. * |