diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-11-07 17:09:24 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-11-07 17:09:24 +1000 |
commit | ecdac378c4d38f3e2c8317b7023819d3d8c2f0c3 (patch) | |
tree | 74011212c7a9ec7d89468b8b71d3d23d7ebbde55 /src/compiler/scala/tools/nsc/transform/Erasure.scala | |
parent | 2dfed21a300724ad61e0863f1cd71260a7ccf507 (diff) | |
parent | ced3ca8ae1aedd37591d85474d9ee85be5c9b56a (diff) | |
download | scala-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.scala | 45 |
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) |