summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala15
1 files changed, 10 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 5e903946c1..db8e203c1c 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -189,18 +189,23 @@ abstract class Erasure extends AddInterfaces
/* Drop redundant types (ones which are implemented by some other parent) from the immediate parents.
* This is important on Android because there is otherwise an interface explosion.
+ * This is now restricted to Scala defined ancestors: a Java defined ancestor may need to be listed
+ * as an immediate parent to support an `invokespecial`.
*/
def minimizeParents(parents: List[Type]): List[Type] = if (parents.isEmpty) parents else {
- def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait
+ def isRedundantParent(sym: Symbol) = sym.isInterface || sym.isTrait
var rest = parents.tail
var leaves = collection.mutable.ListBuffer.empty[Type] += parents.head
while(rest.nonEmpty) {
val candidate = rest.head
- val nonLeaf = leaves exists { t => t.typeSymbol isSubClass candidate.typeSymbol }
- if(!nonLeaf) {
- leaves = leaves filterNot { t => isInterfaceOrTrait(t.typeSymbol) && (candidate.typeSymbol isSubClass t.typeSymbol) }
- leaves += candidate
+ if (candidate.typeSymbol.isJavaDefined && candidate.typeSymbol.isInterface) leaves += candidate
+ else {
+ val nonLeaf = leaves exists { t => t.typeSymbol isSubClass candidate.typeSymbol }
+ if (!nonLeaf) {
+ leaves = leaves filterNot { t => isRedundantParent(t.typeSymbol) && (candidate.typeSymbol isSubClass t.typeSymbol) }
+ leaves += candidate
+ }
}
rest = rest.tail
}