From 87a113f132473036e6b975962fdb5cea8364b532 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 24 Sep 2009 09:30:24 +0000 Subject: moved sortWith from Iterable to Sequence (becau... moved sortWith from Iterable to Sequence (becaus eit does not make sense for sets or maps). Fixed problem interfacing with Java Array[T] parameters. Made manifests compile under 1.5 by avoiding multi-dimensional Array.newInstance. --- .../nsc/symtab/classfile/ClassfileParser.scala | 18 ++++++++++--- src/library/scala/collection/IterableLike.scala | 25 ----------------- src/library/scala/collection/SequenceLike.scala | 31 +++++++++++++++++++++- .../scala/collection/mutable/GenericArray.scala | 2 +- src/library/scala/reflect/ClassManifest.scala | 27 ++++++++----------- src/library/scala/reflect/Manifest.scala | 2 +- 6 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 6f264b3c13..25330bd641 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -545,8 +545,14 @@ abstract class ClassfileParser { val formals = tp.paramTypes assert(formals.last.typeSymbol == definitions.ArrayClass) val method = params.last.owner - val newParams = method.newSyntheticValueParams(formals.init ::: - List(appliedType(definitions.JavaRepeatedParamClass.typeConstructor, List(formals.last.typeArgs.head)))) + val elemtp = formals.last.typeArgs.head match { + case RefinedType(List(t1, t2), _) if (t1.typeSymbol.isAbstractType && t2.typeSymbol == definitions.ObjectClass) => + t1 // drop intersection with Object for abstract types in varargs. UnCurry can handle them. + case t => + t + } + val newParams = method.newSyntheticValueParams( + formals.init ::: List(appliedType(definitions.JavaRepeatedParamClass.typeConstructor, List(elemtp)))) MethodType(newParams, rtpe) case PolyType(tparams, rtpe) => PolyType(tparams, arrayToRepeated(rtpe)) @@ -641,7 +647,13 @@ abstract class ClassfileParser { tpe case ARRAY_TAG => while ('0' <= sig(index) && sig(index) <= '9') index += 1 - appliedType(definitions.ArrayClass.tpe, List(sig2type(tparams, skiptvs))) + var elemtp = sig2type(tparams, skiptvs) + // make unbounded Array[T] where T is a type variable into Array[T with Object] + // (this is necessary because such arrays have a representation which is incompatibe + // with arrays of primitive types. + if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe)) + elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe)) + appliedType(definitions.ArrayClass.tpe, List(elemtp)) case '(' => // we need a method symbol. given in line 486 by calling getType(methodSym, ..) assert(sym ne null) diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala index cd691bb430..49fdbf4868 100644 --- a/src/library/scala/collection/IterableLike.scala +++ b/src/library/scala/collection/IterableLike.scala @@ -312,31 +312,6 @@ self => b.result } - /** Sort the iterable according to the comparison function - * <(e1: a, e2: a) => Boolean, - * which should be true iff e1 is smaller than - * e2. - * The sort is stable. That is elements that are equal wrt `lt` appear in the - * same order in the sorted sequence as in the original. - * - * @param lt the comparison function - * @return an iterable sorted according to the comparison function - * <(e1: a, e2: a) => Boolean. - * @ex
-   *    List("Steve", "Tom", "John", "Bob")
-   *      .sortWith((e1, e2) => (e1 compareTo e2) < 0) =
-   *    List("Bob", "John", "Steve", "Tom")
- */ - def sortWith(lt: (A, A) => Boolean)(implicit m: ClassManifest[A @uncheckedVariance]): Repr = { - // !!! can we supply a default argument to m: ClassManifest ? - val arr = toArray - java.util.Arrays.sort(arr, Ordering fromLessThan lt) - - val b = newBuilder - for (x <- arr) b += x - b.result - } - /** Checks if the other iterable object contains the same elements as this one. * * @note will not terminate for infinite-sized iterables. diff --git a/src/library/scala/collection/SequenceLike.scala b/src/library/scala/collection/SequenceLike.scala index baa4d47646..7223f0f1f7 100644 --- a/src/library/scala/collection/SequenceLike.scala +++ b/src/library/scala/collection/SequenceLike.scala @@ -11,7 +11,7 @@ package scala.collection import generic._ -import mutable.{ListBuffer, HashMap} +import mutable.{ListBuffer, HashMap, GenericArray} // import immutable.{List, Nil, ::} import generic._ @@ -422,6 +422,35 @@ trait SequenceLike[+A, +Repr] extends IterableLike[A, Repr] { self => b.result } + /** Sort the iterable according to the comparison function + * <(e1: a, e2: a) => Boolean, + * which should be true iff e1 is smaller than + * e2. + * The sort is stable. That is elements that are equal wrt `lt` appear in the + * same order in the sorted sequence as in the original. + * + * @param lt the comparison function + * @return an iterable sorted according to the comparison function + * <(e1: a, e2: a) => Boolean. + * @ex
+   *    List("Steve", "Tom", "John", "Bob")
+   *      .sortWith((e1, e2) => (e1 compareTo e2) < 0) =
+   *    List("Bob", "John", "Steve", "Tom")
+ */ + def sortWith(lt: (A, A) => Boolean): Repr = { + val arr = new GenericArray[A](this.length) + var i = 0 + for (x <- this) { + arr(i) = x + i += 1 + } + java.util.Arrays.sort( + arr.array, (Ordering fromLessThan lt).asInstanceOf[Ordering[Object]]) + val b = newBuilder + for (x <- arr) b += x + b.result + } + /** * Overridden for efficiency. * diff --git a/src/library/scala/collection/mutable/GenericArray.scala b/src/library/scala/collection/mutable/GenericArray.scala index 43cc03f07a..87ffd63a82 100644 --- a/src/library/scala/collection/mutable/GenericArray.scala +++ b/src/library/scala/collection/mutable/GenericArray.scala @@ -27,7 +27,7 @@ extends Vector[A] override def companion: Companion[GenericArray] = GenericArray - var array: Array[AnyRef] = new Array[AnyRef](length) + val array: Array[AnyRef] = new Array[AnyRef](length) def apply(idx: Int): A = { if (idx >= length) throw new IndexOutOfBoundsException(idx.toString) diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index 4dc9631710..327054354d 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -72,35 +72,30 @@ trait ClassManifest[T] extends OptManifest[T] { case _ => false } - protected def arrayClass: Predef.Class[Array[T]] = - java.lang.reflect.Array.newInstance(erasure, 0).getClass - .asInstanceOf[Predef.Class[Array[T]]] + protected def arrayClass[T](tp: Predef.Class[_]): Predef.Class[Array[T]] = + java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[Predef.Class[Array[T]]] def arrayManifest: ClassManifest[Array[T]] = - ClassManifest.classType[Array[T]](arrayClass) + ClassManifest.classType[Array[T]](arrayClass[T](erasure)) def newArray(len: Int): Array[T] = java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]] def newArray2(len: Int): Array[Array[T]] = - java.lang.reflect.Array.newInstance( - java.lang.reflect.Array.newInstance(erasure, 0).getClass, len) - .asInstanceOf[Array[Array[T]]] + java.lang.reflect.Array.newInstance(arrayClass[T](erasure), len) + .asInstanceOf[Array[Array[T]]] def newArray3(len: Int): Array[Array[Array[T]]] = - java.lang.reflect.Array.newInstance( - java.lang.reflect.Array.newInstance(erasure, 0, 0).getClass, len) - .asInstanceOf[Array[Array[Array[T]]]] + java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](erasure)), len) + .asInstanceOf[Array[Array[Array[T]]]] def newArray4(len: Int): Array[Array[Array[Array[T]]]] = - java.lang.reflect.Array.newInstance( - java.lang.reflect.Array.newInstance(erasure, 0, 0, 0).getClass, len) - .asInstanceOf[Array[Array[Array[Array[T]]]]] + java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure))), len) + .asInstanceOf[Array[Array[Array[Array[T]]]]] def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] = - java.lang.reflect.Array.newInstance( - java.lang.reflect.Array.newInstance(erasure, 0, 0, 0, 0).getClass, len) - .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]] + java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure)))), len) + .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]] def newWrappedArray(len: Int): WrappedArray[T] = // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index f0c5183e6a..f8a3c13f49 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -30,7 +30,7 @@ trait Manifest[T] extends ClassManifest[T] { override def typeArguments: List[Manifest[_]] = List() override def arrayManifest: Manifest[Array[T]] = - Manifest.classType[Array[T]](arrayClass) + Manifest.classType[Array[T]](arrayClass[T](erasure)) } /** -- cgit v1.2.3