summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/Erasure.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-11-07 17:09:24 +1000
committerJason Zaugg <jzaugg@gmail.com>2014-11-07 17:09:24 +1000
commitecdac378c4d38f3e2c8317b7023819d3d8c2f0c3 (patch)
tree74011212c7a9ec7d89468b8b71d3d23d7ebbde55 /src/compiler/scala/tools/nsc/transform/Erasure.scala
parent2dfed21a300724ad61e0863f1cd71260a7ccf507 (diff)
parentced3ca8ae1aedd37591d85474d9ee85be5c9b56a (diff)
downloadscala-ecdac378c4d38f3e2c8317b7023819d3d8c2f0c3.tar.gz
scala-ecdac378c4d38f3e2c8317b7023819d3d8c2f0c3.tar.bz2
scala-ecdac378c4d38f3e2c8317b7023819d3d8c2f0c3.zip
Merge pull request #4080 from gourlaysama/wip/t8931-redundant-interfaces-2
SI-8931 make generic signature consistent with interface list in classfiles
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/Erasure.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala45
1 files changed, 36 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index db639d0868..b6af19250e 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -185,6 +185,25 @@ abstract class Erasure extends AddInterfaces
private def isErasedValueType(tpe: Type) = tpe.isInstanceOf[ErasedValueType]
+ /* Drop redundant interfaces (ones which are implemented by some other parent) from the immediate parents.
+ * This is important on Android because there is otherwise an interface explosion.
+ */
+ def minimizeInterfaces(lstIfaces: List[Type]): List[Type] = {
+ var rest = lstIfaces
+ var leaves = List.empty[Type]
+ while(!rest.isEmpty) {
+ val candidate = rest.head
+ val nonLeaf = leaves exists { t => t.typeSymbol isSubClass candidate.typeSymbol }
+ if(!nonLeaf) {
+ leaves = candidate :: (leaves filterNot { t => candidate.typeSymbol isSubClass t.typeSymbol })
+ }
+ rest = rest.tail
+ }
+
+ leaves.reverse
+ }
+
+
/** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return
* type for constructors.
*/
@@ -192,16 +211,24 @@ abstract class Erasure extends AddInterfaces
val isTraitSignature = sym0.enclClass.isTrait
def superSig(parents: List[Type]) = {
- val ps = (
- if (isTraitSignature) {
+ def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait
+
+ // a signature should always start with a class
+ def ensureClassAsFirstParent(tps: List[Type]) = tps match {
+ case Nil => ObjectTpe :: Nil
+ case head :: tail if isInterfaceOrTrait(head.typeSymbol) => ObjectTpe :: tps
+ case _ => tps
+ }
+
+ val minParents = minimizeInterfaces(parents)
+ val validParents =
+ if (isTraitSignature)
// java is unthrilled about seeing interfaces inherit from classes
- val ok = parents filter (p => p.typeSymbol.isTrait || p.typeSymbol.isInterface)
- // traits should always list Object.
- if (ok.isEmpty || ok.head.typeSymbol != ObjectClass) ObjectTpe :: ok
- else ok
- }
- else parents
- )
+ minParents filter (p => isInterfaceOrTrait(p.typeSymbol))
+ else minParents
+
+ val ps = ensureClassAsFirstParent(validParents)
+
(ps map boxedSig).mkString
}
def boxedSig(tp: Type) = jsig(tp, primitiveOK = false)