summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/Erasure.scala
diff options
context:
space:
mode:
authorAntoine Gourlay <antoine@gourlay.fr>2015-03-25 19:26:36 +0100
committerAntoine Gourlay <antoine@gourlay.fr>2015-03-25 20:49:53 +0100
commite9bfa33c1eef822eb9d3d0f471f4bbbe390e1e65 (patch)
tree8aa2544f4751871a3e59bd22d563fdea17ab7166 /src/compiler/scala/tools/nsc/transform/Erasure.scala
parent2dc40cc7d7d956a510a9278ab236014f3fb564bc (diff)
downloadscala-e9bfa33c1eef822eb9d3d0f471f4bbbe390e1e65.tar.gz
scala-e9bfa33c1eef822eb9d3d0f471f4bbbe390e1e65.tar.bz2
scala-e9bfa33c1eef822eb9d3d0f471f4bbbe390e1e65.zip
SI-9239 fix java generic signature when traits extend classes
Given the following code: class C1[T] trait T1[T] extends C1[T] class C2[T] extends T1[T] The generic signature of C2 changed after ced3ca8 from "C1[T], T1[T]" to "Object, T1[T]", even though C1 was still marked as a superclass in the bytecode... C1 was removed because a subclass (T1) appeared later on, and it was possible for a trait to cause a class to be evicted. It turns out that if a class A appears in "parents", it *always* has to stay in the signature: if a trait later in the list inherits from some class, that class has to be a superclass of A (per SLS ยง5.1), or A itself, so in any case, the most specific superclass is A, so A should stay in the signature. Thus minimizeParents now only allows traits/interfaces to be removed from the list (the refactoring in 7552739, moving from mixinClasses to parents, makes this much easier to fix). This didn't happen for non-generic signatures because there are two separate fields in the classfile for this (one for the superclass, one for interfaces), so interfaces were processed on their own. Thus non-parametrized classes were not affected. Anything that used erased types at runtime was also fine (like isInstanceOf checks), and anything that used ScalaSignature was also unaffected. Maybethat's why so few things broke... See the test for how this affects Java (hint: badly). This changes very few things when building scala itself, and the changes seem sensible: --- sandbox/lib/scala-library.jar#!scala/runtime/NonLocalReturnControl.class +++ build/pack/lib/scala-library.jar#!scala/runtime/NonLocalReturnControl.class - Generic Signature: <T:Ljava/lang/Object;>Ljava/lang/Object;Lscala/util/control/ControlThrowable; + Generic Signature: <T:Ljava/lang/Object;>Ljava/lang/Throwable;Lscala/util/control/ControlThrowable; --- sandbox/lib/scala-library.jar#!scala/collection/mutable/QueueProxy$$anon$1.class +++ build/pack/lib/scala-library.jar#!scala/collection/mutable/QueueProxy$$anon$1.class - Generic Signature: Ljava/lang/Object;Lscala/collection/mutable/QueueProxy<TA;>; + Generic Signature: Lscala/collection/mutable/Queue<TA;>;Lscala/collection/mutable/QueueProxy<TA;>; --- sandbox/lib/scala-library.jar#!scala/collection/mutable/Iterable$.class +++ build/pack/lib/scala-library.jar#!scala/collection/mutable/Iterable$.class - Generic Signature: Ljava/lang/Object;Lscala/collection/generic/TraversableFactory<Lscala/collection/mutable/Iterable;>; + Generic Signature: Lscala/collection/generic/GenTraversableFactory<Lscala/collection/mutable/Iterable;>;Lscala/collection/generic/TraversableFactory<Lscala/collection/mutable/Iterable;>; --- sandbox/lib/scala-library.jar#!scala/collection/immutable/Traversable$.class +++ build/pack/lib/scala-library.jar#!scala/collection/immutable/Traversable$.class - Generic Signature: Ljava/lang/Object;Lscala/collection/generic/TraversableFactory<Lscala/collection/immutable/Traversable;>; + Generic Signature: Lscala/collection/generic/GenTraversableFactory<Lscala/collection/immutable/Traversable;>;Lscala/collection/generic/TraversableFactory<Lscala/collection/immutable/Traversable;>; --- sandbox/lib/scala-library.jar#!scala/collection/immutable/Iterable$.class +++ build/pack/lib/scala-library.jar#!scala/collection/immutable/Iterable$.class - Generic Signature: Ljava/lang/Object;Lscala/collection/generic/TraversableFactory<Lscala/collection/immutable/Iterable;>; + Generic Signature: Lscala/collection/generic/GenTraversableFactory<Lscala/collection/immutable/Iterable;>;Lscala/collection/generic/TraversableFactory<Lscala/collection/immutable/Iterable;>; --- sandbox/lib/scala-library.jar#!scala/collection/mutable/Traversable$.class +++ build/pack/lib/scala-library.jar#!scala/collection/mutable/Traversable$.class - Generic Signature: Ljava/lang/Object;Lscala/collection/generic/TraversableFactory<Lscala/collection/mutable/Traversable;>; + Generic Signature: Lscala/collection/generic/GenTraversableFactory<Lscala/collection/mutable/Traversable;>;Lscala/collection/generic/TraversableFactory<Lscala/collection/mutable/Traversable;>; --- sandbox/lib/scala-library.jar#!scala/throws.class +++ build/pack/lib/scala-library.jar#!scala/throws.class - Generic Signature: <T:Ljava/lang/Throwable;>Ljava/lang/Object;Lscala/annotation/StaticAnnotation; + Generic Signature: <T:Ljava/lang/Throwable;>Lscala/annotation/Annotation;Lscala/annotation/StaticAnnotation; --- sandbox/lib/scala-library.jar#!scala/collection/mutable/StackProxy$$anon$1.class +++ build/pack/lib/scala-library.jar#!scala/collection/mutable/StackProxy$$anon$1.class - Generic Signature: Ljava/lang/Object;Lscala/collection/mutable/StackProxy<TA;>; + Generic Signature: Lscala/collection/mutable/Stack<TA;>;Lscala/collection/mutable/StackProxy<TA;>; --- sandbox/lib/scala-library.jar#!scala/collection/convert/Wrappers$IterableWrapper.class +++ build/pack/lib/scala-library.jar#!scala/collection/convert/Wrappers$IterableWrapper.class - Generic Signature: <A:Ljava/lang/Object;>Ljava/lang/Object;Lscala/collection/convert/Wrappers$IterableWrapperTrait<TA;>;Lscala/Product;Lscala/Serializable; + Generic Signature: <A:Ljava/lang/Object;>Ljava/util/AbstractCollection<TA;>;Lscala/collection/convert/Wrappers$IterableWrapperTrait<TA;>;Lscala/Product;Lscala/Serializable; --- sandbox/lib/scala-library.jar#!scala/collection/Iterable$.class +++ build/pack/lib/scala-library.jar#!scala/collection/Iterable$.class - Generic Signature: Ljava/lang/Object;Lscala/collection/generic/TraversableFactory<Lscala/collection/Iterable;>; + Generic Signature: Lscala/collection/generic/GenTraversableFactory<Lscala/collection/Iterable;>;Lscala/collection/generic/TraversableFactory<Lscala/collection/Iterable;>; --- sandbox/lib/scala-library.jar#!scala/collection/Traversable$.class +++ build/pack/lib/scala-library.jar#!scala/collection/Traversable$.class - Generic Signature: Ljava/lang/Object;Lscala/collection/generic/TraversableFactory<Lscala/collection/Traversable;>; + Generic Signature: Lscala/collection/generic/GenTraversableFactory<Lscala/collection/Traversable;>;Lscala/collection/generic/TraversableFactory<Lscala/collection/Traversable;>; --- sandbox/lib/scala-library.jar#!scala/collection/parallel/AdaptiveWorkStealingForkJoinTasks$WrappedTask.class +++ build/pack/lib/scala-library.jar#!scala/collection/parallel/AdaptiveWorkStealingForkJoinTasks$WrappedTask.class - Generic Signature: <R:Ljava/lang/Object;Tp:Ljava/lang/Object;>Ljava/lang/Object;Lscala/collection/parallel/ForkJoinTasks$WrappedTask<TR;TTp;>;Lscala/collection/parallel/AdaptiveWorkStealingTasks$WrappedTask<TR;TTp;>; + Generic Signature: <R:Ljava/lang/Object;Tp:Ljava/lang/Object;>Lscala/concurrent/forkjoin/RecursiveAction;Lscala/collection/parallel/ForkJoinTasks$WrappedTask<TR;TTp;>;Lscala/collection/parallel/AdaptiveWorkStealingTasks$WrappedTask<TR;TTp;>;
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/Erasure.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 5c72bb3258..438d39bc86 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -188,14 +188,16 @@ 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.
*/
- def minimizeParents(parents: List[Type]): List[Type] = {
- var rest = parents
- var leaves = collection.mutable.ListBuffer.empty[Type]
+ def minimizeParents(parents: List[Type]): List[Type] = if (parents.isEmpty) parents else {
+ def isInterfaceOrTrait(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 => candidate.typeSymbol isSubClass t.typeSymbol }
+ leaves = leaves filterNot { t => isInterfaceOrTrait(t.typeSymbol) && (candidate.typeSymbol isSubClass t.typeSymbol) }
leaves += candidate
}
rest = rest.tail