From e9bfa33c1eef822eb9d3d0f471f4bbbe390e1e65 Mon Sep 17 00:00:00 2001 From: Antoine Gourlay Date: Wed, 25 Mar 2015 19:26:36 +0100 Subject: SI-9239 fix java generic signature when traits extend classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: Ljava/lang/Object;Lscala/util/control/ControlThrowable; + Generic Signature: 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; + Generic Signature: Lscala/collection/mutable/Queue;Lscala/collection/mutable/QueueProxy; --- 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; + Generic Signature: Lscala/collection/generic/GenTraversableFactory;Lscala/collection/generic/TraversableFactory; --- 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; + Generic Signature: Lscala/collection/generic/GenTraversableFactory;Lscala/collection/generic/TraversableFactory; --- 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; + Generic Signature: Lscala/collection/generic/GenTraversableFactory;Lscala/collection/generic/TraversableFactory; --- 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; + Generic Signature: Lscala/collection/generic/GenTraversableFactory;Lscala/collection/generic/TraversableFactory; --- sandbox/lib/scala-library.jar#!scala/throws.class +++ build/pack/lib/scala-library.jar#!scala/throws.class - Generic Signature: Ljava/lang/Object;Lscala/annotation/StaticAnnotation; + Generic Signature: 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; + Generic Signature: Lscala/collection/mutable/Stack;Lscala/collection/mutable/StackProxy; --- 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: Ljava/lang/Object;Lscala/collection/convert/Wrappers$IterableWrapperTrait;Lscala/Product;Lscala/Serializable; + Generic Signature: Ljava/util/AbstractCollection;Lscala/collection/convert/Wrappers$IterableWrapperTrait;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; + Generic Signature: Lscala/collection/generic/GenTraversableFactory;Lscala/collection/generic/TraversableFactory; --- 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; + Generic Signature: Lscala/collection/generic/GenTraversableFactory;Lscala/collection/generic/TraversableFactory; --- 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: Ljava/lang/Object;Lscala/collection/parallel/ForkJoinTasks$WrappedTask;Lscala/collection/parallel/AdaptiveWorkStealingTasks$WrappedTask; + Generic Signature: Lscala/concurrent/forkjoin/RecursiveAction;Lscala/collection/parallel/ForkJoinTasks$WrappedTask;Lscala/collection/parallel/AdaptiveWorkStealingTasks$WrappedTask; --- src/compiler/scala/tools/nsc/transform/Erasure.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/compiler') 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 -- cgit v1.2.3