summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-01-11 02:05:17 -0800
committerJason Zaugg <jzaugg@gmail.com>2014-01-11 02:05:17 -0800
commita8122413c0cf2e51cdfd32c0450b91910f8a8cc2 (patch)
tree0019f1c40119916352c4c9a902662e3784418b5d
parentaefe3fb844b9ae81068867f4aa19df5f96cd462f (diff)
parent5876e8c62130b4089b146d4fea5bcd926e47bf6f (diff)
downloadscala-a8122413c0cf2e51cdfd32c0450b91910f8a8cc2.tar.gz
scala-a8122413c0cf2e51cdfd32c0450b91910f8a8cc2.tar.bz2
scala-a8122413c0cf2e51cdfd32c0450b91910f8a8cc2.zip
Merge pull request #3345 from retronym/ticket/8114
[nomaster] Binary compat. workaround for erasure bug
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala27
-rw-r--r--test/files/run/t8114.scala15
2 files changed, 41 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.
*
diff --git a/test/files/run/t8114.scala b/test/files/run/t8114.scala
new file mode 100644
index 0000000000..ecbca37d2a
--- /dev/null
+++ b/test/files/run/t8114.scala
@@ -0,0 +1,15 @@
+class AbstractTable[T] { type TableElementType }
+class Table[T] extends AbstractTable[T] { type TableElementType = T }
+
+class Query[E, U]
+class TableQuery[E <: AbstractTable[_]] extends Query[E, E#TableElementType]
+
+object Test extends App {
+ object MyTable extends TableQuery[Table[Long]]
+
+ def list[R](q: Query[_, R]): List[R] = Nil
+ list/*[Long]*/(MyTable) collect { case x => x }
+
+ // Generates a redundant bridge method (double definition error)
+ // in 2.10.x due to (at least) the bug in erasure fixed in SI-7120
+}