diff options
author | Vojin Jovanovic <vojin.jovanovic@epfl.ch> | 2012-01-09 18:11:10 +0100 |
---|---|---|
committer | Vojin Jovanovic <vojin.jovanovic@epfl.ch> | 2012-01-09 18:11:10 +0100 |
commit | 1126912bce5d098571c1bd29a04e4781e19c3d85 (patch) | |
tree | 79e753014c1adfa26e39e32911125bfc0ad8ee4c /src/library | |
parent | 5a4b555c378d79d57b59dfd6edafd2b9a59866bb (diff) | |
parent | 820491ed6376e9f8f8a8102387495113dce55444 (diff) | |
download | scala-1126912bce5d098571c1bd29a04e4781e19c3d85.tar.gz scala-1126912bce5d098571c1bd29a04e4781e19c3d85.tar.bz2 scala-1126912bce5d098571c1bd29a04e4781e19c3d85.zip |
Merge branch 'master' into execution-context
Diffstat (limited to 'src/library')
48 files changed, 675 insertions, 310 deletions
diff --git a/src/library/scala/Either.scala b/src/library/scala/Either.scala index bc75f0f088..e454cdf5ec 100644 --- a/src/library/scala/Either.scala +++ b/src/library/scala/Either.scala @@ -575,15 +575,15 @@ object Either { } } - /** If the condition is satisfied, return the given `A` in `Left`, - * otherwise, return the given `B` in `Right`. + /** If the condition is satisfied, return the given `B` in `Right`, + * otherwise, return the given `A` in `Left`. * * {{{ * val userInput: String = ... * Either.cond( * userInput.forall(_.isDigit) && userInput.size == 10, - * "The input (%s) does not look like a phone number".format(userInput), - * PhoneNumber(userInput) + * PhoneNumber(userInput), + * "The input (%s) does not look like a phone number".format(userInput) * }}} */ def cond[A, B](test: Boolean, right: => B, left: => A): Either[A, B] = diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index c967a48abc..3d85f2f52f 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -48,19 +48,20 @@ import java.util.regex.Pattern * * @param initial The initial value from which to count the integers that * identifies values at run-time. - * @param names The sequence of names to give to this enumeration's values. - * * @author Matthias Zenger */ @SerialVersionUID(8476000850333817230L) -abstract class Enumeration(initial: Int, - @deprecated("Names should be specified individually or discovered via reflection", "2.10") - names: String*) extends Serializable { +abstract class Enumeration (initial: Int) extends Serializable { thisenum => def this() = this(0) - - @deprecated("Names should be specified individually or discovered via reflection", "2.10") + + @deprecated("Names should be specified individually or discovered via reflection", "2.10.0") + def this(initial: Int, names: String*) = { + this(initial) + this.nextName = names.iterator + } + @deprecated("Names should be specified individually or discovered via reflection", "2.10.0") def this(names: String*) = this(0, names: _*) /* Note that `readResolve` cannot be private, since otherwise @@ -97,12 +98,13 @@ abstract class Enumeration(initial: Int, } /** The integer to use to identify the next created value. */ - protected var nextId = initial + protected var nextId: Int = initial /** The string to use to name the next created value. */ - protected var nextName = names.iterator + protected var nextName: Iterator[String] = _ + private def nextNameOrNull = - if (nextName.hasNext) nextName.next else null + if (nextName != null && nextName.hasNext) nextName.next else null /** The highest integer amongst those used to identify values in this * enumeration. */ @@ -120,17 +122,8 @@ abstract class Enumeration(initial: Int, */ final def apply(x: Int): Value = vmap(x) - /** - * Return a `Value` from this `Enumeration` whose name matches - * the argument `s`. - * - * You can pass a String* set of names to the constructor, or initialize - * each `Enumeration` with `Value(String)`. Otherwise, the names are - * determined automatically through reflection. - * - * Note the change here wrt 2.7 is intentional. You should know whether - * a name is in an `Enumeration` beforehand. If not, just use find on - * values. + /** Return a `Value` from this `Enumeration` whose name matches + * the argument `s`. The names are determined automatically via reflection. * * @param s an `Enumeration` name * @return the `Value` of this `Enumeration` if its name matches `s` diff --git a/src/library/scala/MatchingStrategy.scala b/src/library/scala/MatchingStrategy.scala index 4eaf7852b8..d11598bad6 100644 --- a/src/library/scala/MatchingStrategy.scala +++ b/src/library/scala/MatchingStrategy.scala @@ -1,32 +1,27 @@ package scala abstract class MatchingStrategy[M[+x]] { + // runs the matcher on the given input + def runOrElse[T, U](in: T)(matcher: T => M[U]): U + def zero: M[Nothing] def one[T](x: T): M[T] - def guard[T](cond: Boolean, then: => T): M[T] // = if(cond) one(then) else zero - def altFlatMap[T, U](f: T => M[U])(a: M[U], b: M[T]): M[U] // = a orElse b.flatMap(f) -- can't easily&efficiently express M[T] should have flatMap and orElse - def runOrElse[T, U](x: T)(f: T => M[U]): U - def isSuccess[T, U](x: T)(f: T => M[U]): Boolean - - // find the first alternative to successfully flatMap f - // to avoid code explosion due to alternatives - def or[T, U](f: T => M[U], alts: M[T]*) = (alts foldLeft (zero: M[U]))(altFlatMap(f)) + def guard[T](cond: Boolean, then: => T): M[T] + def isSuccess[T, U](x: T)(f: T => M[U]): Boolean // used for isDefinedAt def caseResult[T](x: T): M[T] = one(x) // used as a marker to distinguish the RHS of a case (case pat => RHS) and intermediate successes - // when deriving a partial function from a pattern match, we need to - // distinguish the RHS of a case, which should not be evaluated when computing isDefinedAt, + // when deriving a partial function from a pattern match, + // we need to distinguish the RHS of a case, which should not be evaluated when computing isDefinedAt, // from an intermediate result (which must be computed) - } object MatchingStrategy { implicit object OptionMatchingStrategy extends MatchingStrategy[Option] { type M[+x] = Option[x] - @inline def guard[T](cond: Boolean, then: => T): M[T] = if(cond) Some(then) else None + @inline def runOrElse[T, U](x: T)(f: T => M[U]): U = f(x) getOrElse (throw new MatchError(x)) @inline def zero: M[Nothing] = None @inline def one[T](x: T): M[T] = Some(x) - @inline def altFlatMap[T, U](f: T => M[U])(a: M[U], b: M[T]): M[U] = a orElse b.flatMap(f) - @inline def runOrElse[T, U](x: T)(f: T => M[U]): U = f(x) getOrElse (throw new MatchError(x)) + @inline def guard[T](cond: Boolean, then: => T): M[T] = if(cond) Some(then) else None @inline def isSuccess[T, U](x: T)(f: T => M[U]): Boolean = !f(x).isEmpty } }
\ No newline at end of file diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index bd498de847..6db4904b93 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -192,6 +192,13 @@ sealed abstract class Option[+A] extends Product with Serializable { @inline final def exists(p: A => Boolean): Boolean = !isEmpty && p(this.get) + /** Returns true if this option is empty '''or''' the predicate + * $p returns true when applied to this $option's value. + * + * @param p the predicate to test + */ + @inline final def forall(p: A => Boolean): Boolean = isEmpty || p(this.get) + /** Apply the given procedure $f to the option's value, * if it is nonempty. Otherwise, do nothing. * diff --git a/src/library/scala/Symbol.scala b/src/library/scala/Symbol.scala index 8a17ae87b0..8851f1ab91 100644 --- a/src/library/scala/Symbol.scala +++ b/src/library/scala/Symbol.scala @@ -31,8 +31,8 @@ final class Symbol private (val name: String) extends Serializable { override def equals(other: Any) = this eq other.asInstanceOf[AnyRef] } -object Symbol extends UniquenessCache[String, Symbol] -{ +object Symbol extends UniquenessCache[String, Symbol] { + override def apply(name: String): Symbol = super.apply(name) protected def valueFromKey(name: String): Symbol = new Symbol(name) protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name) } diff --git a/src/library/scala/annotation/migration.scala b/src/library/scala/annotation/migration.scala index c2e392b807..8ab12a7c8e 100644 --- a/src/library/scala/annotation/migration.scala +++ b/src/library/scala/annotation/migration.scala @@ -14,15 +14,17 @@ package scala.annotation * reason or another retain the same name and type signature, * but some aspect of their behavior is different. An illustrative * examples is Stack.iterator, which reversed from LIFO to FIFO - * order between scala 2.7 and 2.8. + * order between Scala 2.7 and 2.8. * - * The version numbers are to mark the scala major/minor release - * version where the change took place. + * @param message A message describing the change, which is emitted + * by the compiler if the flag `-Xmigration` is set. + * + * @param changedIn The version, in which the behaviour change was + * introduced. * * @since 2.8 */ -private[scala] final class migration( - majorVersion: Int, - minorVersion: Int, - message: String) -extends annotation.StaticAnnotation {} + private[scala] final class migration(message: String, changedIn: String) extends annotation.StaticAnnotation { + @deprecated("Use the constructor taking two Strings instead.", "2.10") + def this(majorVersion: Int, minorVersion: Int, message: String) = this(message, majorVersion + "." + minorVersion) + }
\ No newline at end of file diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala index dc89bcf85d..122eec2d90 100644 --- a/src/library/scala/collection/GenTraversableLike.scala +++ b/src/library/scala/collection/GenTraversableLike.scala @@ -123,10 +123,7 @@ trait GenTraversableLike[+A, +Repr] extends GenTraversableOnce[A] with Paralleli * @param bf $bfinfo * @return collection with intermediate results */ - @migration(2, 9, - "This scanRight definition has changed in 2.9.\n" + - "The previous behavior can be reproduced with scanRight.reverse." - ) + @migration("The behavior of `scanRight` has changed. The previous behavior can be reproduced with scanRight.reverse.", "2.9.0") def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That /** Applies a function `f` to all elements of this $coll. diff --git a/src/library/scala/collection/GenTraversableViewLike.scala b/src/library/scala/collection/GenTraversableViewLike.scala index 9f7bbadfb2..78e0773fb0 100644 --- a/src/library/scala/collection/GenTraversableViewLike.scala +++ b/src/library/scala/collection/GenTraversableViewLike.scala @@ -12,8 +12,6 @@ package scala.collection import generic._ import mutable.{ Builder, ArrayBuffer } import TraversableView.NoBuilder -import annotation.migration - trait GenTraversableViewLike[+A, diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 7b780ba2e4..d46d215e0c 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -9,7 +9,7 @@ package scala.collection import mutable.ArrayBuffer -import annotation.{ tailrec, migration } +import annotation.migration import immutable.Stream /** The `Iterator` object provides various functions for creating specialized iterators. @@ -52,7 +52,7 @@ object Iterator { /** Creates iterator that produces the results of some element computation a number of times. * - * @param n the number of elements returned by the iterator. + * @param len the number of elements returned by the iterator. * @param elem the element computation * @return An iterator that produces the results of `n` evaluations of `elem`. */ @@ -66,7 +66,7 @@ object Iterator { /** Creates an iterator producing the values of a given function over a range of integer values starting from 0. * - * @param n The number of elements returned by the iterator + * @param end The number of elements returned by the iterator * @param f The function computing element values * @return An iterator that produces the values `f(0), ..., f(n -1)`. */ @@ -410,10 +410,7 @@ trait Iterator[+A] extends TraversableOnce[A] { * which `pf` is defined the image `pf(x)`. * @note Reuse: $consumesAndProducesIterator */ - @migration(2, 8, - "This collect implementation bears no relationship to the one before 2.8.\n"+ - "The previous behavior can be reproduced with toSeq." - ) + @migration("`collect` has changed. The previous behavior can be reproduced with `toSeq`.", "2.8.0") def collect[B](pf: PartialFunction[A, B]): Iterator[B] = { val self = buffered new AbstractIterator[B] { @@ -1033,9 +1030,9 @@ trait Iterator[+A] extends TraversableOnce[A] { /** Returns this iterator with patched values. * - * @param from The start index from which to patch - * @param ps The iterator of patch values - * @param replaced The number of values in the original iterator that are replaced by the patch. + * @param from The start index from which to patch + * @param patchElems The iterator of patch values + * @param replaced The number of values in the original iterator that are replaced by the patch. * @note Reuse: $consumesTwoAndProducesOneIterator */ def patch[B >: A](from: Int, patchElems: Iterator[B], replaced: Int): Iterator[B] = new AbstractIterator[B] { diff --git a/src/library/scala/collection/LinearSeqLike.scala b/src/library/scala/collection/LinearSeqLike.scala index 75c1edac66..ceb980ff80 100644 --- a/src/library/scala/collection/LinearSeqLike.scala +++ b/src/library/scala/collection/LinearSeqLike.scala @@ -13,6 +13,7 @@ import generic._ import mutable.ListBuffer import immutable.List import scala.util.control.Breaks._ +import annotation.tailrec /** A template trait for linear sequences of type `LinearSeq[A]`. * @@ -69,4 +70,9 @@ trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]] extends SeqLike[A, Repr xs } } + + @tailrec override final def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Boolean = { + if (this.isEmpty) that.isEmpty + else that.nonEmpty && p(head, that.head) && (tail corresponds that.tail)(p) + } } diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala index 1653a011d6..07116e99dd 100644 --- a/src/library/scala/collection/MapLike.scala +++ b/src/library/scala/collection/MapLike.scala @@ -182,14 +182,14 @@ self => * * @return the keys of this map as an iterable. */ - @migration(2, 8, "As of 2.8, keys returns Iterable[A] rather than Iterator[A].") + @migration("`keys` returns `Iterable[A]` rather than `Iterator[A]`.", "2.8.0") def keys: Iterable[A] = keySet /** Collects all values of this map in an iterable collection. * * @return the values of this map as an iterable. */ - @migration(2, 8, "As of 2.8, values returns Iterable[B] rather than Iterator[B].") + @migration("`values` returns `Iterable[B]` rather than `Iterator[B]`.", "2.8.0") def values: Iterable[B] = new DefaultValuesIterable /** The implementation class of the iterable returned by `values`. diff --git a/src/library/scala/collection/SetLike.scala b/src/library/scala/collection/SetLike.scala index b4695363de..7293f3775c 100644 --- a/src/library/scala/collection/SetLike.scala +++ b/src/library/scala/collection/SetLike.scala @@ -89,7 +89,7 @@ self => // note: this is only overridden here to add the migration annotation, // which I hope to turn into an Xlint style warning as the migration aspect // is not central to its importance. - @migration(2, 8, "Set.map now returns a Set, so it will discard duplicate values.") + @migration("Set.map now returns a Set, so it will discard duplicate values.", "2.8.0") override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[This, B, That]): That = super.map(f)(bf) /** Tests if some element is contained in this set. diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index 4f0fec1de3..e2acc0b3e0 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -390,10 +390,7 @@ trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr] b.result } - @migration(2, 9, - "This scanRight definition has changed in 2.9.\n" + - "The previous behavior can be reproduced with scanRight.reverse." - ) + @migration("The behavior of `scanRight` has changed. The previous behavior can be reproduced with scanRight.reverse.", "2.9.0") def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { var scanned = List(z) var acc = z diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala index 8c67d841bc..fbecad98fe 100644 --- a/src/library/scala/collection/TraversableViewLike.scala +++ b/src/library/scala/collection/TraversableViewLike.scala @@ -185,16 +185,19 @@ trait TraversableViewLike[+A, override def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[This, B, That]): That = newForced(thisSeq.scanLeft(z)(op)).asInstanceOf[That] - @migration(2, 9, - "This scanRight definition has changed in 2.9.\n" + - "The previous behavior can be reproduced with scanRight.reverse." - ) + @migration("The behavior of `scanRight` has changed. The previous behavior can be reproduced with scanRight.reverse.", "2.9.0") override def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[This, B, That]): That = newForced(thisSeq.scanRight(z)(op)).asInstanceOf[That] override def groupBy[K](f: A => K): immutable.Map[K, This] = thisSeq groupBy f mapValues (xs => newForced(xs)) + override def unzip[A1, A2](implicit asPair: A => (A1, A2)) = + (newMapped(x => asPair(x)._1), newMapped(x => asPair(x)._2)) // TODO - Performance improvements. + + override def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3)) = + (newMapped(x => asTriple(x)._1), newMapped(x => asTriple(x)._2), newMapped(x => asTriple(x)._3)) // TODO - Performance improvements. + override def toString = viewToString } diff --git a/src/library/scala/collection/generic/GenericTraversableTemplate.scala b/src/library/scala/collection/generic/GenericTraversableTemplate.scala index 10cd3b5755..12c1a75c7a 100644 --- a/src/library/scala/collection/generic/GenericTraversableTemplate.scala +++ b/src/library/scala/collection/generic/GenericTraversableTemplate.scala @@ -13,7 +13,6 @@ package generic import mutable.Builder import annotation.migration -import annotation.bridge import annotation.unchecked.uncheckedVariance /** A template class for companion objects of ``regular`` collection classes @@ -148,7 +147,7 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew * @throws `IllegalArgumentException` if all collections in this $coll * are not of the same size. */ - @migration(2, 9, "As of 2.9, transpose throws an exception if collections are not uniformly sized.") + @migration("`transpose` throws an `IllegalArgumentException` if collections are not uniformly sized.", "2.9.0") def transpose[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]): CC[CC[B] @uncheckedVariance] = { if (isEmpty) return genericBuilder[CC[B]].result diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 531eac6c01..c6f056bd81 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -277,6 +277,9 @@ sealed abstract class List[+A] extends AbstractSeq[A] override def toStream : Stream[A] = if (isEmpty) Stream.Empty else new Stream.Cons(head, tail.toStream) + + @deprecated("use `distinct` instead", "2.8.0") + def removeDuplicates: List[A] = distinct } /** The empty list. @@ -343,6 +346,8 @@ final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extend */ object List extends SeqFactory[List] { + import scala.collection.{Iterable, Seq, IndexedSeq} + /** $genericCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, List[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] @@ -352,6 +357,248 @@ object List extends SeqFactory[List] { override def empty[A]: List[A] = Nil override def apply[A](xs: A*): List[A] = xs.toList + + /** Create a sorted list with element values `v,,>n+1,, = step(v,,n,,)` + * where `v,,0,, = start` and elements are in the range between `start` + * (inclusive) and `end` (exclusive). + * + * @param start the start value of the list + * @param end the end value of the list + * @param step the increment function of the list, which given `v,,n,,`, + * computes `v,,n+1,,`. Must be monotonically increasing + * or decreasing. + * @return the sorted list of all integers in range `[start;end)`. + */ + @deprecated("use `iterate` instead", "2.8.0") + def range(start: Int, end: Int, step: Int => Int): List[Int] = { + val up = step(start) > start + val down = step(start) < start + val b = new ListBuffer[Int] + var i = start + while ((!up || i < end) && (!down || i > end)) { + b += i + val next = step(i) + if (i == next) + throw new IllegalArgumentException("the step function did not make any progress on "+ i) + i = next + } + b.toList + } + + /** Create a list containing several copies of an element. + * + * @param n the length of the resulting list + * @param elem the element composing the resulting list + * @return a list composed of `n` elements all equal to `elem` + */ + @deprecated("use `fill` instead", "2.8.0") + def make[A](n: Int, elem: A): List[A] = { + val b = new ListBuffer[A] + var i = 0 + while (i < n) { + b += elem + i += 1 + } + b.toList + } + + /** Concatenate all the elements of a given list of lists. + * + * @param xss the list of lists that are to be concatenated + * @return the concatenation of all the lists + */ + @deprecated("use `xss.flatten` instead of `List.flatten(xss)`", "2.8.0") + def flatten[A](xss: List[List[A]]): List[A] = { + val b = new ListBuffer[A] + for (xs <- xss) { + var xc = xs + while (!xc.isEmpty) { + b += xc.head + xc = xc.tail + } + } + b.toList + } + + /** Transforms a list of pairs into a pair of lists. + * + * @param xs the list of pairs to unzip + * @return a pair of lists. + */ + @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0") + def unzip[A,B](xs: List[(A,B)]): (List[A], List[B]) = { + val b1 = new ListBuffer[A] + val b2 = new ListBuffer[B] + var xc = xs + while (!xc.isEmpty) { + b1 += xc.head._1 + b2 += xc.head._2 + xc = xc.tail + } + (b1.toList, b2.toList) + } + + /** Transforms an iterable of pairs into a pair of lists. + * + * @param xs the iterable of pairs to unzip + * @return a pair of lists. + */ + @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0") + def unzip[A,B](xs: Iterable[(A,B)]): (List[A], List[B]) = + xs.foldRight[(List[A], List[B])]((Nil, Nil)) { + case ((x, y), (xs, ys)) => (x :: xs, y :: ys) + } + + /** + * Returns the `Left` values in the given `Iterable` of `Either`s. + */ + @deprecated("use `xs collect { case Left(x: A) => x }` instead of `List.lefts(xs)`", "2.8.0") + def lefts[A, B](es: Iterable[Either[A, B]]) = + es.foldRight[List[A]](Nil)((e, as) => e match { + case Left(a) => a :: as + case Right(_) => as + }) + + /** + * Returns the `Right` values in the given `Iterable` of `Either`s. + */ + @deprecated("use `xs collect { case Right(x: B) => x }` instead of `List.rights(xs)`", "2.8.0") + def rights[A, B](es: Iterable[Either[A, B]]) = + es.foldRight[List[B]](Nil)((e, bs) => e match { + case Left(_) => bs + case Right(b) => b :: bs + }) + + /** Transforms an Iterable of Eithers into a pair of lists. + * + * @param xs the iterable of Eithers to separate + * @return a pair of lists. + */ + @deprecated("use `(for (Left(x) <- es) yield x, for (Right(x) <- es) yield x)` instead", "2.8.0") + def separate[A,B](es: Iterable[Either[A, B]]): (List[A], List[B]) = + es.foldRight[(List[A], List[B])]((Nil, Nil)) { + case (Left(a), (lefts, rights)) => (a :: lefts, rights) + case (Right(b), (lefts, rights)) => (lefts, b :: rights) + } + + /** Converts an iterator to a list. + * + * @param it the iterator to convert + * @return a list that contains the elements returned by successive + * calls to `it.next` + */ + @deprecated("use `it.toList` instead of `List.toList(it)`", "2.8.0") + def fromIterator[A](it: Iterator[A]): List[A] = it.toList + + /** Converts an array into a list. + * + * @param arr the array to convert + * @return a list that contains the same elements than `arr` + * in the same order + */ + @deprecated("use `array.toList` instead of `List.fromArray(array)`", "2.8.0") + def fromArray[A](arr: Array[A]): List[A] = fromArray(arr, 0, arr.length) + + /** Converts a range of an array into a list. + * + * @param arr the array to convert + * @param start the first index to consider + * @param len the length of the range to convert + * @return a list that contains the same elements than `arr` + * in the same order + */ + @deprecated("use `array.view(start, end).toList` instead of `List.fromArray(array, start, end)`", "2.8.0") + def fromArray[A](arr: Array[A], start: Int, len: Int): List[A] = { + var res: List[A] = Nil + var i = start + len + while (i > start) { + i -= 1 + res = arr(i) :: res + } + res + } + + /** Returns the list resulting from applying the given function `f` + * to corresponding elements of the argument lists. + * + * @param f function to apply to each pair of elements. + * @return `[f(a,,0,,,b,,0,,), ..., f(a,,n,,,b,,n,,)]` if the lists are + * `[a,,0,,, ..., a,,k,,]`, `[b,,0,,, ..., b,,l,,]` and + * `n = min(k,l)` + */ + @deprecated("use `(xs, ys).zipped.map(f)` instead of `List.map2(xs, ys)(f)`", "2.8.0") + def map2[A,B,C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = { + val b = new ListBuffer[C] + var xc = xs + var yc = ys + while (!xc.isEmpty && !yc.isEmpty) { + b += f(xc.head, yc.head) + xc = xc.tail + yc = yc.tail + } + b.toList + } + + /** Tests whether the given predicate `p` holds + * for all corresponding elements of the argument lists. + * + * @param p function to apply to each pair of elements. + * @return `(p(a<sub>0</sub>,b<sub>0</sub>) && + * ... && p(a<sub>n</sub>,b<sub>n</sub>))]` + * if the lists are `[a<sub>0</sub>, ..., a<sub>k</sub>]`; + * `[b<sub>0</sub>, ..., b<sub>l</sub>]` + * and `n = min(k,l)` + */ + @deprecated("use `(xs, ys).zipped.forall(f)` instead of `List.forall2(xs, ys)(f)`", "2.8.0") + def forall2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { + var xc = xs + var yc = ys + while (!xc.isEmpty && !yc.isEmpty) { + if (!f(xc.head, yc.head)) return false + xc = xc.tail + yc = yc.tail + } + true + } + + /** Tests whether the given predicate `p` holds + * for some corresponding elements of the argument lists. + * + * @param p function to apply to each pair of elements. + * @return `n != 0 && (p(a<sub>0</sub>,b<sub>0</sub>) || + * ... || p(a<sub>n</sub>,b<sub>n</sub>))]` if the lists are + * `[a<sub>0</sub>, ..., a<sub>k</sub>]`, + * `[b<sub>0</sub>, ..., b<sub>l</sub>]` and + * `n = min(k,l)` + */ + @deprecated("use `(xs, ys).zipped.exists(f)` instead of `List.exists2(xs, ys)(f)`", "2.8.0") + def exists2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { + var xc = xs + var yc = ys + while (!xc.isEmpty && !yc.isEmpty) { + if (f(xc.head, yc.head)) return true + xc = xc.tail + yc = yc.tail + } + false + } + + /** Transposes a list of lists. + * pre: All element lists have the same length. + * + * @param xss the list of lists + * @return the transposed list of lists + */ + @deprecated("use `xss.transpose` instead of `List.transpose(xss)`", "2.8.0") + def transpose[A](xss: List[List[A]]): List[List[A]] = { + val buf = new ListBuffer[List[A]] + var yss = xss + while (!yss.head.isEmpty) { + buf += (yss map (_.head)) + yss = (yss map (_.tail)) + } + buf.toList + } } /** Only used for list serialization */ diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index 45cf088dd9..bbefd983fd 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -47,6 +47,7 @@ trait Map[A, +B] extends Iterable[(A, B)] def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1] = new Map.WithDefault[A, B1](this, d) /** The same map with a given default value. + * Note: `get`, `contains`, `iterator`, `keys`, etc are not affected by `withDefaultValue`. * * Invoking transformer methods (e.g. `map`) will not preserve the default value. * diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index e891f8bec8..c92c0268b6 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -51,15 +51,35 @@ extends collection.AbstractSeq[Int] { override def par = new ParRange(this) - // This member is designed to enforce conditions: - // (step != 0) && (length <= Int.MaxValue), - // but cannot be evaluated eagerly because we have a pattern where ranges - // are constructed like: "x to y by z" - // The "x to y" piece should not trigger an exception. So the calculation - // is delayed, which means it will not fail fast for those cases where failing - // was correct. - private lazy val numRangeElements: Int = Range.count(start, end, step, isInclusive) - + private def gap = end.toLong - start.toLong + private def isExact = gap % step == 0 + private def hasStub = isInclusive || !isExact + private def longLength = gap / step + ( if (hasStub) 1 else 0 ) + + // Check cannot be evaluated eagerly because we have a pattern where + // ranges are constructed like: "x to y by z" The "x to y" piece + // should not trigger an exception. So the calculation is delayed, + // which means it will not fail fast for those cases where failing was + // correct. + override final val isEmpty = ( + (start > end && step > 0) + || (start < end && step < 0) + || (start == end && !isInclusive) + ) + final val numRangeElements: Int = { + if (step == 0) throw new IllegalArgumentException("step cannot be 0.") + else if (isEmpty) 0 + else { + val len = longLength + if (len > scala.Int.MaxValue) -1 + else len.toInt + } + } + final val lastElement = start + (numRangeElements - 1) * step + final val terminalElement = start + numRangeElements * step + + override def last = if (isEmpty) Nil.last else lastElement + protected def copy(start: Int, end: Int, step: Int): Range = new Range(start, end, step) /** Create a new range with the `start` and `end` values of this range and @@ -71,31 +91,49 @@ extends collection.AbstractSeq[Int] def isInclusive = false + override def size = length + override def length = if (numRangeElements < 0) fail() else numRangeElements + + private def description = "%d %s %d by %s".format(start, if (isInclusive) "to" else "until", end, step) + private def fail() = throw new IllegalArgumentException(description + ": seqs cannot contain more than Int.MaxValue elements.") + private def validateMaxLength() { + if (numRangeElements < 0) + fail() + } + + def validateRangeBoundaries(f: Int => Any): Boolean = { + validateMaxLength() + + start != Int.MinValue || end != Int.MinValue || { + var count = 0 + var num = start + while (count < numRangeElements) { + f(num) + count += 1 + num += step + } + false + } + } + + @inline final def apply(idx: Int): Int = { + validateMaxLength() + if (idx < 0 || idx >= numRangeElements) throw new IndexOutOfBoundsException(idx.toString) + else start + (step * idx) + } + @inline final override def foreach[@specialized(Unit) U](f: Int => U) { - if (length > 0) { - val last = this.last + if (validateRangeBoundaries(f)) { var i = start - while (i != last) { + val terminal = terminalElement + val step = this.step + while (i != terminal) { f(i) i += step } - f(i) } } - override def length: Int = numRangeElements - override lazy val last: Int = - if (length == 0) Nil.last - else locationAfterN(length - 1) - - final override def isEmpty = length == 0 - - @inline - final def apply(idx: Int): Int = { - if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException(idx.toString) - locationAfterN(idx) - } - /** Creates a new range containing the first `n` elements of this range. * * $doesNotUseBuilders @@ -104,8 +142,8 @@ extends collection.AbstractSeq[Int] * @return a new range consisting of `n` first elements. */ final override def take(n: Int): Range = ( - if (n <= 0 || length == 0) newEmptyRange(start) - else if (n >= length) this + if (n <= 0 || isEmpty) newEmptyRange(start) + else if (n >= numRangeElements) this else new Range.Inclusive(start, locationAfterN(n - 1), step) ) @@ -117,8 +155,8 @@ extends collection.AbstractSeq[Int] * @return a new range consisting of all the elements of this range except `n` first elements. */ final override def drop(n: Int): Range = ( - if (n <= 0 || length == 0) this - else if (n >= length) newEmptyRange(end) + if (n <= 0 || isEmpty) this + else if (n >= numRangeElements) newEmptyRange(end) else copy(locationAfterN(n), end, step) ) @@ -153,7 +191,7 @@ extends collection.AbstractSeq[Int] var current = start var counted = 0 - while (counted < length && p(current)) { + while (counted < numRangeElements && p(current)) { counted += 1 current += step } @@ -161,7 +199,7 @@ extends collection.AbstractSeq[Int] } // Tests whether a number is within the endpoints, without testing // whether it is a member of the sequence (i.e. when step > 1.) - private def isWithinBoundaries(elem: Int) = (length > 0) && ( + private def isWithinBoundaries(elem: Int) = !isEmpty && ( (step > 0 && start <= elem && elem <= last ) || (step < 0 && last <= elem && elem <= start) ) @@ -190,21 +228,21 @@ extends collection.AbstractSeq[Int] * * $doesNotUseBuilders */ - final override def takeRight(n: Int): Range = drop(length - n) + final override def takeRight(n: Int): Range = drop(numRangeElements - n) /** Creates a new range consisting of the initial `length - n` elements of the range. * * $doesNotUseBuilders */ - final override def dropRight(n: Int): Range = take(length - n) + final override def dropRight(n: Int): Range = take(numRangeElements - n) /** Returns the reverse of this range. * * $doesNotUseBuilders */ final override def reverse: Range = - if (length > 0) new Range.Inclusive(last, start, -step) - else this + if (isEmpty) this + else new Range.Inclusive(last, start, -step) /** Make range inclusive. */ @@ -215,10 +253,9 @@ extends collection.AbstractSeq[Int] final def contains(x: Int) = isWithinBoundaries(x) && ((x - start) % step == 0) final override def sum[B >: Int](implicit num: Numeric[B]): Int = { - val len = length - if (len == 0) 0 - else if (len == 1) head - else (len.toLong * (head + last) / 2).toInt + if (isEmpty) 0 + else if (numRangeElements == 1) head + else (numRangeElements.toLong * (head + last) / 2).toInt } override def toIterable = this @@ -228,7 +265,7 @@ extends collection.AbstractSeq[Int] override def equals(other: Any) = other match { case x: Range => (x canEqual this) && (length == x.length) && ( - (length == 0) || // all empty sequences are equal + isEmpty || // all empty sequences are equal (start == x.start && last == x.last) // same length and same endpoints implies equality ) case _ => @@ -239,7 +276,7 @@ extends collection.AbstractSeq[Int] */ override def toString() = { - val endStr = if (length > Range.MAX_PRINT) ", ... )" else ")" + val endStr = if (numRangeElements > Range.MAX_PRINT) ", ... )" else ")" take(Range.MAX_PRINT).mkString("Range(", ", ", endStr) } } @@ -350,3 +387,4 @@ object Range { // super.foreach(f) } } +
\ No newline at end of file diff --git a/src/library/scala/collection/mutable/BufferLike.scala b/src/library/scala/collection/mutable/BufferLike.scala index acf26e59eb..1dc2fc27d5 100644 --- a/src/library/scala/collection/mutable/BufferLike.scala +++ b/src/library/scala/collection/mutable/BufferLike.scala @@ -152,7 +152,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] def prepend(elems: A*) { prependAll(elems) } /** Prepends the elements contained in a traversable object to this buffer. - * @param elems the collection containing the elements to prepend. + * @param xs the collection containing the elements to prepend. */ def prependAll(xs: TraversableOnce[A]) { xs ++=: this } @@ -220,10 +220,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] * @param xs the traversable object. * @return a new collection consisting of all the elements of this collection and `xs`. */ - @migration(2, 8, - "As of 2.8, ++ always creates a new collection, even on Buffers.\n"+ - "Use ++= instead if you intend to add by side effect to an existing collection.\n" - ) + @migration("`++` creates a new buffer. Use `++=` to add an element from this buffer and return that buffer itself.", "2.8.0") def ++(xs: GenTraversableOnce[A]): This = clone() ++= xs.seq @bridge @@ -234,10 +231,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] * @param elem the element to remove. * @return a new collection consisting of all the elements of this collection except `elem`. */ - @migration(2, 8, - "As of 2.8, - always creates a new collection, even on Buffers.\n"+ - "Use -= instead if you intend to remove by side effect from an existing collection.\n" - ) + @migration("`-` creates a new buffer. Use `-=` to remove an element from this buffer and return that buffer itself.", "2.8.0") override def -(elem: A): This = clone() -= elem /** Creates a new collection with all the elements of this collection except the two @@ -249,10 +243,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] * @return a new collection consisting of all the elements of this collection except * `elem1`, `elem2` and those in `elems`. */ - @migration(2, 8, - "As of 2.8, - always creates a new collection, even on Buffers.\n"+ - "Use -= instead if you intend to remove by side effect from an existing collection.\n" - ) + @migration("`-` creates a new buffer. Use `-=` to remove an element from this buffer and return that buffer itself.", "2.8.0") override def -(elem1: A, elem2: A, elems: A*): This = clone() -= elem1 -= elem2 --= elems /** Creates a new collection with all the elements of this collection except those @@ -262,10 +253,7 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] * @return a new collection with all the elements of this collection except * those in `xs` */ - @migration(2, 8, - "As of 2.8, -- always creates a new collection, even on Buffers.\n"+ - "Use --= instead if you intend to remove by side effect from an existing collection.\n" - ) + @migration("`--` creates a new buffer. Use `--=` to remove an element from this buffer and return that buffer itself.", "2.8.0") override def --(xs: GenTraversableOnce[A]): This = clone() --= xs.seq @bridge def --(xs: TraversableOnce[A]): This = --(xs: GenTraversableOnce[A]) diff --git a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala index 7ad2f9558f..dfb70beeda 100644 --- a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala +++ b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala @@ -91,7 +91,7 @@ trait DoubleLinkedListLike[A, This <: Seq[A] with DoubleLinkedListLike[A, This]] * current node, i.e. `this` node itself will still point "into" the list it * was in. */ - @migration(2, 9, "Double linked list now removes the current node from the list.") + @migration("Double linked list now removes the current node from the list.", "2.9.0") def remove(): Unit = if (nonEmpty) { next.prev = prev if (prev ne null) prev.next = next // because this could be the first node diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala index 0740d97e09..f3fb6738eb 100644 --- a/src/library/scala/collection/mutable/FlatHashTable.scala +++ b/src/library/scala/collection/mutable/FlatHashTable.scala @@ -24,7 +24,7 @@ package mutable trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { import FlatHashTable._ - private final val tableDebug = false + private final def tableDebug = false @transient private[collection] var _loadFactor = defaultLoadFactor @@ -43,11 +43,19 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { /** The array keeping track of number of elements in 32 element blocks. */ @transient protected var sizemap: Array[Int] = null - + + @transient var seedvalue: Int = tableSizeSeed + import HashTable.powerOfTwo + protected def capacity(expectedSize: Int) = if (expectedSize == 0) 1 else powerOfTwo(expectedSize) + private def initialCapacity = capacity(initialSize) - + + protected def randomSeed = seedGenerator.get.nextInt() + + protected def tableSizeSeed = Integer.bitCount(table.length - 1) + /** * Initializes the collection from the input stream. `f` will be called for each element * read from the input stream in the order determined by the stream. This is useful for @@ -57,23 +65,25 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { */ private[collection] def init(in: java.io.ObjectInputStream, f: A => Unit) { in.defaultReadObject - - _loadFactor = in.readInt + + _loadFactor = in.readInt() assert(_loadFactor > 0) - - val size = in.readInt + + val size = in.readInt() tableSize = 0 assert(size >= 0) - + table = new Array(capacity(sizeForThreshold(size, _loadFactor))) threshold = newThreshold(_loadFactor, table.size) - - val smDefined = in.readBoolean + + seedvalue = in.readInt() + + val smDefined = in.readBoolean() if (smDefined) sizeMapInit(table.length) else sizemap = null - + var index = 0 while (index < size) { - val elem = in.readObject.asInstanceOf[A] + val elem = in.readObject().asInstanceOf[A] f(elem) addEntry(elem) index += 1 @@ -89,6 +99,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { out.defaultWriteObject out.writeInt(_loadFactor) out.writeInt(tableSize) + out.writeInt(seedvalue) out.writeBoolean(isSizeMapDefined) iterator.foreach(out.writeObject) } @@ -125,6 +136,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { if (entry == elem) return false h = (h + 1) % table.length entry = table(h) + //Statistics.collisions += 1 } table(h) = elem.asInstanceOf[AnyRef] tableSize = tableSize + 1 @@ -185,6 +197,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { table = new Array[AnyRef](table.length * 2) tableSize = 0 nnSizeMapReset(table.length) + seedvalue = tableSizeSeed threshold = newThreshold(_loadFactor, table.length) var i = 0 while (i < oldtable.length) { @@ -280,10 +293,24 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { /* End of size map handling code */ protected final def index(hcode: Int) = { + // version 1 (no longer used - did not work with parallel hash tables) // improve(hcode) & (table.length - 1) - val improved = improve(hcode) + + // version 2 (allows for parallel hash table construction) + val improved = improve(hcode, seedvalue) val ones = table.length - 1 (improved >>> (32 - java.lang.Integer.bitCount(ones))) & ones + + // version 3 (solves SI-5293 in most cases, but such a case would still arise for parallel hash tables) + // val hc = improve(hcode) + // val bbp = blockbitpos + // val ones = table.length - 1 + // val needed = Integer.bitCount(ones) + // val blockbits = ((hc >>> bbp) & 0x1f) << (needed - 5) + // val rest = ((hc >>> (bbp + 5)) << bbp) | (((1 << bbp) - 1) & hc) + // val restmask = (1 << (needed - 5)) - 1 + // val improved = blockbits | (rest & restmask) + // improved } protected def clearTable() { @@ -298,6 +325,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { table, tableSize, threshold, + seedvalue, sizemap ) @@ -307,6 +335,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { table = c.table tableSize = c.tableSize threshold = c.threshold + seedvalue = c.seedvalue sizemap = c.sizemap } if (alwaysInitSizeMap && sizemap == null) sizeMapInitAndRebuild @@ -315,21 +344,30 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { } - private[collection] object FlatHashTable { - + + /** Creates a specific seed to improve hashcode of a hash table instance + * and ensure that iteration order vulnerabilities are not 'felt' in other + * hash tables. + * + * See SI-5293. + */ + final def seedGenerator = new ThreadLocal[util.Random] { + override def initialValue = new util.Random + } + /** The load factor for the hash table; must be < 500 (0.5) */ - private[collection] def defaultLoadFactor: Int = 450 - private[collection] final def loadFactorDenum = 1000 + def defaultLoadFactor: Int = 450 + final def loadFactorDenum = 1000 /** The initial size of the hash table. */ - private[collection] def initialSize: Int = 16 + def initialSize: Int = 32 - private[collection] def sizeForThreshold(size: Int, _loadFactor: Int) = (size.toLong * loadFactorDenum / _loadFactor).toInt + def sizeForThreshold(size: Int, _loadFactor: Int) = math.max(32, (size.toLong * loadFactorDenum / _loadFactor).toInt) - private[collection] def newThreshold(_loadFactor: Int, size: Int) = { + def newThreshold(_loadFactor: Int, size: Int) = { val lf = _loadFactor assert(lf < (loadFactorDenum / 2), "loadFactor too large; must be < 0.5") (size.toLong * lf / loadFactorDenum ).toInt @@ -340,6 +378,7 @@ private[collection] object FlatHashTable { val table: Array[AnyRef], val tableSize: Int, val threshold: Int, + val seedvalue: Int, val sizemap: Array[Int] ) @@ -352,16 +391,24 @@ private[collection] object FlatHashTable { if (elem == null) throw new IllegalArgumentException("Flat hash tables cannot contain null elements.") else elem.hashCode() - protected final def improve(hcode: Int) = { - // var h: Int = hcode + ~(hcode << 9) - // h = h ^ (h >>> 14) - // h = h + (h << 4) - // h ^ (h >>> 10) + protected final def improve(hcode: Int, seed: Int) = { + //var h: Int = hcode + ~(hcode << 9) + //h = h ^ (h >>> 14) + //h = h + (h << 4) + //h ^ (h >>> 10) + var i = hcode * 0x9e3775cd i = java.lang.Integer.reverseBytes(i) - i * 0x9e3775cd + val improved = i * 0x9e3775cd + + // for the remainder, see SI-5293 + // to ensure that different bits are used for different hash tables, we have to rotate based on the seed + val rotation = seed % 32 + val rotated = (improved >>> rotation) | (improved << (32 - rotation)) + rotated } } } + diff --git a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala index 32fca1117c..3232179dbb 100644 --- a/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala +++ b/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala @@ -46,12 +46,12 @@ extends AbstractMap[A, B] override def keysIterator: Iterator[A] = imap.keysIterator - @migration(2, 8, "As of 2.8, keys returns Iterable[A] rather than Iterator[A].") + @migration("`keys` returns Iterable[A] rather than Iterator[A].", "2.8.0") override def keys: collection.Iterable[A] = imap.keys override def valuesIterator: Iterator[B] = imap.valuesIterator - @migration(2, 8, "As of 2.8, values returns Iterable[B] rather than Iterator[B].") + @migration("`values` returns Iterable[B] rather than Iterator[B].", "2.8.0") override def values: collection.Iterable[B] = imap.values def iterator: Iterator[(A, B)] = imap.iterator diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala index e4b1458e53..b08a4b7bc9 100644 --- a/src/library/scala/collection/mutable/MapLike.scala +++ b/src/library/scala/collection/mutable/MapLike.scala @@ -90,10 +90,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @param kv the key/value mapping to be added * @return a new map containing mappings of this map and the mapping `kv`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new map. To add an element as a\n"+ - "side effect to an existing map and return that map itself, use +=." - ) + @migration("`+` creates a new map. Use `+=` to add an element to this map and return that map itself.", "2.8.0") def + [B1 >: B] (kv: (A, B1)): Map[A, B1] = clone().asInstanceOf[Map[A, B1]] += kv /** Creates a new map containing two or more key/value mappings and all the key/value @@ -106,10 +103,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @param elems the remaining elements to add. * @return a new map containing mappings of this map and two or more specified mappings. */ - @migration(2, 8, - "As of 2.8, this operation creates a new map. To add an element as a\n"+ - "side effect to an existing map and return that map itself, use +=." - ) + @migration("`+` creates a new map. Use `+=` to add an element to this map and return that map itself.", "2.8.0") override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): Map[A, B1] = clone().asInstanceOf[Map[A, B1]] += elem1 += elem2 ++= elems @@ -121,10 +115,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @param xs the traversable object. * @return a new map containing mappings of this map and those provided by `xs`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new map. To add the elements as a\n"+ - "side effect to an existing map and return that map itself, use ++=." - ) + @migration("`++` creates a new map. Use `++=` to add an element to this map and return that map itself.", "2.8.0") override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1] = clone().asInstanceOf[Map[A, B1]] ++= xs.seq @@ -154,10 +145,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @param key the key to be removed * @return a new map with all the mappings of this map except that with a key `key`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new map. To remove an element as a\n"+ - "side effect to an existing map and return that map itself, use -=." - ) + @migration("`-` creates a new map. Use `-=` to remove an element from this map and return that map itself.", "2.8.0") override def -(key: A): This = clone() -= key /** Removes all bindings from the map. After this operation has completed, @@ -223,10 +211,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return a new map containing all the mappings of this map except mappings * with a key equal to `elem1`, `elem2` or any of `elems`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new map. To remove an element as a\n"+ - "side effect to an existing map and return that map itself, use -=." - ) + @migration("`-` creates a new map. Use `-=` to remove an element from this map and return that map itself.", "2.8.0") override def -(elem1: A, elem2: A, elems: A*): This = clone() -= elem1 -= elem2 --= elems @@ -237,10 +222,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] * @return a new map with all the key/value mappings of this map except mappings * with a key equal to a key from `xs`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new map. To remove the elements as a\n"+ - "side effect to an existing map and return that map itself, use --=." - ) + @migration("`--` creates a new map. Use `--=` to remove an element from this map and return that map itself.", "2.8.0") override def --(xs: GenTraversableOnce[A]): This = clone() --= xs.seq @bridge def --(xs: TraversableOnce[A]): This = --(xs: GenTraversableOnce[A]) diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index 23a68c1d3e..381cb09e18 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -12,7 +12,7 @@ package scala.collection package mutable import generic._ -import annotation.{migration, bridge} +import annotation.bridge /** This class implements priority queues using a heap. * To prioritize elements of type A there must be an implicit diff --git a/src/library/scala/collection/mutable/SetLike.scala b/src/library/scala/collection/mutable/SetLike.scala index c5eeb1ae7f..5e201d9959 100644 --- a/src/library/scala/collection/mutable/SetLike.scala +++ b/src/library/scala/collection/mutable/SetLike.scala @@ -141,10 +141,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]] * @param elem the element to add. * @return a new set consisting of elements of this set and `elem`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new set. To add an element as a\n"+ - "side effect to an existing set and return that set itself, use +=." - ) + @migration("`+` creates a new set. Use `+=` to add an element to this set and return that set itself.", "2.8.0") override def + (elem: A): This = clone() += elem /** Creates a new set consisting of all the elements of this set and two or more @@ -158,10 +155,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]] * @return a new set consisting of all the elements of this set, `elem1`, * `elem2` and those in `elems`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new set. To add the elements as a\n"+ - "side effect to an existing set and return that set itself, use +=." - ) + @migration("`+` creates a new set. Use `+=` to add an element to this set and return that set itself.", "2.8.0") override def + (elem1: A, elem2: A, elems: A*): This = clone() += elem1 += elem2 ++= elems @@ -173,10 +167,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]] * @param xs the traversable object. * @return a new set consisting of elements of this set and those in `xs`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new set. To add the elements as a\n"+ - "side effect to an existing set and return that set itself, use ++=." - ) + @migration("`++` creates a new set. Use `++=` to add elements to this set and return that set itself.", "2.8.0") override def ++(xs: GenTraversableOnce[A]): This = clone() ++= xs.seq @bridge def ++(xs: TraversableOnce[A]): This = ++(xs: GenTraversableOnce[A]) @@ -186,10 +177,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]] * @param elem the element to remove. * @return a new set consisting of all the elements of this set except `elem`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new set. To remove the element as a\n"+ - "side effect to an existing set and return that set itself, use -=." - ) + @migration("`-` creates a new set. Use `-=` to remove an element from this set and return that set itself.", "2.8.0") override def -(elem: A): This = clone() -= elem /** Creates a new set consisting of all the elements of this set except the two @@ -201,10 +189,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]] * @return a new set consisting of all the elements of this set except * `elem1`, `elem2` and `elems`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new set. To remove the elements as a\n"+ - "side effect to an existing set and return that set itself, use -=." - ) + @migration("`-` creates a new set. Use `-=` to remove an element from this set and return that set itself.", "2.8.0") override def -(elem1: A, elem2: A, elems: A*): This = clone() -= elem1 -= elem2 --= elems @@ -215,10 +200,7 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]] * @return a new set consisting of all the elements of this set except * elements from `xs`. */ - @migration(2, 8, - "As of 2.8, this operation creates a new set. To remove the elements as a\n"+ - "side effect to an existing set and return that set itself, use --=." - ) + @migration("`--` creates a new set. Use `--=` to remove elements from this set and return that set itself.", "2.8.0") override def --(xs: GenTraversableOnce[A]): This = clone() --= xs.seq @bridge def --(xs: TraversableOnce[A]): This = --(xs: GenTraversableOnce[A]) diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala index ffac3b78b7..8fad131009 100644 --- a/src/library/scala/collection/mutable/Stack.scala +++ b/src/library/scala/collection/mutable/Stack.scala @@ -156,17 +156,17 @@ extends AbstractSeq[A] * * @return an iterator over all stack elements. */ - @migration(2, 8, "Stack iterator and foreach now traverse in FIFO order.") + @migration("`iterator` traverses in FIFO order.", "2.8.0") override def iterator: Iterator[A] = elems.iterator /** Creates a list of all stack elements in LIFO order. * * @return the created list. */ - @migration(2, 8, "Stack iterator and foreach now traverse in FIFO order.") + @migration("`toList` traverses in FIFO order.", "2.8.0") override def toList: List[A] = elems - @migration(2, 8, "Stack iterator and foreach now traverse in FIFO order.") + @migration("`foreach` traverses in FIFO order.", "2.8.0") override def foreach[U](f: A => U): Unit = super.foreach(f) /** This method clones the stack. diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 603086d209..d9ad58f054 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -403,7 +403,7 @@ final class StringBuilder(private val underlying: JavaStringBuilder) * * @return the reversed StringBuilder */ - @migration(2, 8, "Since 2.8 reverse returns a new instance. Use 'reverseContents' to update in place.") + @migration("`reverse` returns a new instance. Use `reverseContents` to update in place and return that StringBuilder itself.", "2.8.0") override def reverse: StringBuilder = new StringBuilder(new JavaStringBuilder(underlying) reverse) override def clone(): StringBuilder = new StringBuilder(new JavaStringBuilder(underlying)) diff --git a/src/library/scala/collection/mutable/SynchronizedMap.scala b/src/library/scala/collection/mutable/SynchronizedMap.scala index 8b2c6faa41..6e3ae13ada 100644 --- a/src/library/scala/collection/mutable/SynchronizedMap.scala +++ b/src/library/scala/collection/mutable/SynchronizedMap.scala @@ -40,14 +40,14 @@ trait SynchronizedMap[A, B] extends Map[A, B] { override def getOrElseUpdate(key: A, default: => B): B = synchronized { super.getOrElseUpdate(key, default) } override def transform(f: (A, B) => B): this.type = synchronized[this.type] { super.transform(f) } override def retain(p: (A, B) => Boolean): this.type = synchronized[this.type] { super.retain(p) } - @migration(2, 8, "As of 2.8, values returns Iterable[B] rather than Iterator[B].") + @migration("`values` returns `Iterable[B]` rather than `Iterator[B]`.", "2.8.0") override def values: collection.Iterable[B] = synchronized { super.values } override def valuesIterator: Iterator[B] = synchronized { super.valuesIterator } override def clone(): Self = synchronized { super.clone() } override def foreach[U](f: ((A, B)) => U) = synchronized { super.foreach(f) } override def apply(key: A): B = synchronized { super.apply(key) } override def keySet: collection.Set[A] = synchronized { super.keySet } - @migration(2, 8, "As of 2.8, keys returns Iterable[A] rather than Iterator[A].") + @migration("`keys` returns `Iterable[A]` rather than `Iterator[A]`.", "2.8.0") override def keys: collection.Iterable[A] = synchronized { super.keys } override def keysIterator: Iterator[A] = synchronized { super.keysIterator } override def isEmpty: Boolean = synchronized { super.isEmpty } diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala index 2a10458457..350e64739f 100644 --- a/src/library/scala/collection/parallel/immutable/ParRange.scala +++ b/src/library/scala/collection/parallel/immutable/ParRange.scala @@ -88,7 +88,7 @@ self => /* accessors */ override def foreach[U](f: Int => U): Unit = { - rangeleft.foreach(f) + rangeleft.foreach(f.asInstanceOf[Int => Unit]) ind = len } diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala index 37065e32fc..31750b0b0d 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala @@ -190,7 +190,7 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntr } else { // construct a normal table and fill it sequentially // TODO parallelize by keeping separate sizemaps and merging them - val table = new HashTable[K, DefaultEntry[K, V]] { + object table extends HashTable[K, DefaultEntry[K, V]] { def insertEntry(e: DefaultEntry[K, V]) = if (super.findEntry(e.key) eq null) super.addEntry(e) sizeMapInit(table.length) } @@ -201,8 +201,7 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntr } i += 1 } - val c = table.hashTableContents - new ParHashMap(c) + new ParHashMap(table.hashTableContents) } /* classes */ diff --git a/src/library/scala/collection/parallel/mutable/ParHashSet.scala b/src/library/scala/collection/parallel/mutable/ParHashSet.scala index 9dbc7dc6c4..7763cdf318 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashSet.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashSet.scala @@ -119,10 +119,11 @@ with collection.mutable.FlatHashTable.HashUtils[T] { import collection.parallel.tasksupport._ private var mask = ParHashSetCombiner.discriminantmask private var nonmasklen = ParHashSetCombiner.nonmasklength - + private var seedvalue = 27 + def +=(elem: T) = { sz += 1 - val hc = improve(elemHashCode(elem)) + val hc = improve(elemHashCode(elem), seedvalue) val pos = hc >>> nonmasklen if (buckets(pos) eq null) { // initialize bucket @@ -140,7 +141,7 @@ with collection.mutable.FlatHashTable.HashUtils[T] { private def parPopulate: FlatHashTable.Contents[T] = { // construct it in parallel - val table = new AddingFlatHashTable(size, tableLoadFactor) + val table = new AddingFlatHashTable(size, tableLoadFactor, seedvalue) val (inserted, leftovers) = executeAndWaitResult(new FillBlocks(buckets, table, 0, buckets.length)) var leftinserts = 0 for (elem <- leftovers) leftinserts += table.insertEntry(0, table.tableLength, elem.asInstanceOf[T]) @@ -153,6 +154,7 @@ with collection.mutable.FlatHashTable.HashUtils[T] { // TODO parallelize by keeping separate size maps and merging them val tbl = new FlatHashTable[T] { sizeMapInit(table.length) + seedvalue = ParHashSetCombiner.this.seedvalue } for { buffer <- buckets; @@ -168,13 +170,13 @@ with collection.mutable.FlatHashTable.HashUtils[T] { * it has to take and allocates the underlying hash table in advance. * Elements can only be added to it. The final size has to be adjusted manually. * It is internal to `ParHashSet` combiners. - * */ - class AddingFlatHashTable(numelems: Int, lf: Int) extends FlatHashTable[T] { + class AddingFlatHashTable(numelems: Int, lf: Int, inseedvalue: Int) extends FlatHashTable[T] { _loadFactor = lf table = new Array[AnyRef](capacity(FlatHashTable.sizeForThreshold(numelems, _loadFactor))) tableSize = 0 threshold = FlatHashTable.newThreshold(_loadFactor, table.length) + seedvalue = inseedvalue sizeMapInit(table.length) override def toString = "AFHT(%s)".format(table.length) @@ -310,6 +312,7 @@ with collection.mutable.FlatHashTable.HashUtils[T] { } + private[parallel] object ParHashSetCombiner { private[mutable] val discriminantbits = 5 private[mutable] val numblocks = 1 << discriminantbits diff --git a/src/library/scala/io/Codec.scala b/src/library/scala/io/Codec.scala index 487f9c7b87..1a27df1c10 100644 --- a/src/library/scala/io/Codec.scala +++ b/src/library/scala/io/Codec.scala @@ -97,19 +97,28 @@ object Codec extends LowPriorityCodecImplicits { new Codec(decoder.charset()) { override def decoder = _decoder } } - @migration(2, 9, "This method was previously misnamed `toUTF8`. Converts from Array[Byte] to Array[Char].") - def fromUTF8(bytes: Array[Byte]): Array[Char] = { - val bbuffer = java.nio.ByteBuffer wrap bytes + @migration("This method was previously misnamed `toUTF8`. Converts from Array[Byte] to Array[Char].", "2.9.0") + def fromUTF8(bytes: Array[Byte]): Array[Char] = fromUTF8(bytes, 0, bytes.length) + def fromUTF8(bytes: Array[Byte], offset: Int, len: Int): Array[Char] = { + val bbuffer = java.nio.ByteBuffer.wrap(bytes, offset, len) val cbuffer = UTF8.charSet decode bbuffer - val chars = new Array[Char](cbuffer.remaining()) + val chars = new Array[Char](cbuffer.remaining()) cbuffer get chars chars } - @migration(2, 9, "This method was previously misnamed `fromUTF8`. Converts from character sequence to Array[Byte].") + @migration("This method was previously misnamed `fromUTF8`. Converts from character sequence to Array[Byte].", "2.9.0") def toUTF8(cs: CharSequence): Array[Byte] = { - val cbuffer = java.nio.CharBuffer wrap cs + val cbuffer = java.nio.CharBuffer.wrap(cs, 0, cs.length) + val bbuffer = UTF8.charSet encode cbuffer + val bytes = new Array[Byte](bbuffer.remaining()) + bbuffer get bytes + + bytes + } + def toUTF8(chars: Array[Char], offset: Int, len: Int): Array[Byte] = { + val cbuffer = java.nio.CharBuffer.wrap(chars, offset, len) val bbuffer = UTF8.charSet encode cbuffer val bytes = new Array[Byte](bbuffer.remaining()) bbuffer get bytes diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index 553fb08c18..497de92c80 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -13,7 +13,6 @@ import java.{ lang => jl } import java.math.{ MathContext, BigDecimal => BigDec } import scala.collection.immutable.NumericRange -import annotation.migration /** * @author Stephane Micheloud diff --git a/src/library/scala/math/Ordered.scala b/src/library/scala/math/Ordered.scala index b67146942f..53d618db63 100644 --- a/src/library/scala/math/Ordered.scala +++ b/src/library/scala/math/Ordered.scala @@ -58,11 +58,11 @@ trait Ordered[A] extends java.lang.Comparable[A] { * * Returns `x` where: * - * - `x < 0` when `this > that` + * - `x < 0` when `this < that` * * - `x == 0` when `this == that` * - * - `x < 0` when `this > that` + * - `x > 0` when `this > that` * */ def compare(that: A): Int diff --git a/src/library/scala/math/Ordering.scala b/src/library/scala/math/Ordering.scala index b23165154c..8fc74a9d5d 100644 --- a/src/library/scala/math/Ordering.scala +++ b/src/library/scala/math/Ordering.scala @@ -10,7 +10,7 @@ package scala.math import java.util.Comparator -/** Ordering is trait whose instances each represent a strategy for sorting +/** Ordering is a trait whose instances each represent a strategy for sorting * instances of a type. * * Ordering's companion object defines many implicit objects to deal with @@ -262,12 +262,52 @@ object Ordering extends LowPriorityOrderingImplicits { implicit object Long extends LongOrdering trait FloatOrdering extends Ordering[Float] { + outer => + def compare(x: Float, y: Float) = java.lang.Float.compare(x, y) + + override def lteq(x: Float, y: Float): Boolean = x <= y + override def gteq(x: Float, y: Float): Boolean = x >= y + override def lt(x: Float, y: Float): Boolean = x < y + override def gt(x: Float, y: Float): Boolean = x > y + override def equiv(x: Float, y: Float): Boolean = x == y + override def max(x: Float, y: Float): Float = math.max(x, y) + override def min(x: Float, y: Float): Float = math.min(x, y) + + override def reverse: Ordering[Float] = new FloatOrdering { + override def reverse = outer + override def compare(x: Float, y: Float) = outer.compare(y, x) + + override def lteq(x: Float, y: Float): Boolean = outer.lteq(y, x) + override def gteq(x: Float, y: Float): Boolean = outer.gteq(y, x) + override def lt(x: Float, y: Float): Boolean = outer.lt(y, x) + override def gt(x: Float, y: Float): Boolean = outer.gt(y, x) + } } implicit object Float extends FloatOrdering trait DoubleOrdering extends Ordering[Double] { + outer => + def compare(x: Double, y: Double) = java.lang.Double.compare(x, y) + + override def lteq(x: Double, y: Double): Boolean = x <= y + override def gteq(x: Double, y: Double): Boolean = x >= y + override def lt(x: Double, y: Double): Boolean = x < y + override def gt(x: Double, y: Double): Boolean = x > y + override def equiv(x: Double, y: Double): Boolean = x == y + override def max(x: Double, y: Double): Double = math.max(x, y) + override def min(x: Double, y: Double): Double = math.min(x, y) + + override def reverse: Ordering[Double] = new DoubleOrdering { + override def reverse = outer + override def compare(x: Double, y: Double) = outer.compare(y, x) + + override def lteq(x: Double, y: Double): Boolean = outer.lteq(y, x) + override def gteq(x: Double, y: Double): Boolean = outer.gteq(y, x) + override def lt(x: Double, y: Double): Boolean = outer.lt(y, x) + override def gt(x: Double, y: Double): Boolean = outer.gt(y, x) + } } implicit object Double extends DoubleOrdering diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index acd28f04f5..466b57dea7 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -127,7 +127,7 @@ trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable { java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[jClass[Array[T]]] def arrayManifest: ClassManifest[Array[T]] = - ClassManifest.classType[Array[T]](arrayClass[T](erasure)) + ClassManifest.classType[Array[T]](arrayClass[T](erasure), this) def newArray(len: Int): Array[T] = java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]] @@ -220,7 +220,7 @@ object ClassManifest { new ClassTypeManifest[T](Some(prefix), clazz, args.toList) def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match { - case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]] + case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]] case m: ClassManifest[_] => m.asInstanceOf[ClassManifest[T]].arrayManifest } diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index df5f64cdf6..be08409636 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -44,7 +44,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals { override def typeArguments: List[Manifest[_]] = Nil override def arrayManifest: Manifest[Array[T]] = - Manifest.classType[Array[T]](arrayClass[T](erasure)) + Manifest.classType[Array[T]](arrayClass[T](erasure), this) override def canEqual(that: Any): Boolean = that match { case _: Manifest[_] => true @@ -60,7 +60,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals { override def hashCode = this.erasure.## } -trait AnyValManifest[T] extends Manifest[T] with Equals { +sealed abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Manifest.Any) || (that eq Manifest.AnyVal) override def canEqual(other: Any) = other match { @@ -68,7 +68,7 @@ trait AnyValManifest[T] extends Manifest[T] with Equals { case _ => false } override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) + override val hashCode = System.identityHashCode(this) } /** The object `Manifest` defines factory methods for manifests. @@ -76,127 +76,104 @@ trait AnyValManifest[T] extends Manifest[T] with Equals { * in client code. */ object Manifest { - private def ObjectClass = classOf[java.lang.Object] + def valueManifests: List[AnyValManifest[_]] = + List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) - val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte] { + val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte]("Byte") { def erasure = java.lang.Byte.TYPE - override def toString = "Byte" override def newArray(len: Int): Array[Byte] = new Array[Byte](len) override def newWrappedArray(len: Int): WrappedArray[Byte] = new WrappedArray.ofByte(new Array[Byte](len)) override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte() private def readResolve(): Any = Manifest.Byte } - val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short] { + val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short]("Short") { def erasure = java.lang.Short.TYPE - override def toString = "Short" override def newArray(len: Int): Array[Short] = new Array[Short](len) override def newWrappedArray(len: Int): WrappedArray[Short] = new WrappedArray.ofShort(new Array[Short](len)) override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort() private def readResolve(): Any = Manifest.Short } - val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char] { + val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char]("Char") { def erasure = java.lang.Character.TYPE - override def toString = "Char" override def newArray(len: Int): Array[Char] = new Array[Char](len) override def newWrappedArray(len: Int): WrappedArray[Char] = new WrappedArray.ofChar(new Array[Char](len)) override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar() private def readResolve(): Any = Manifest.Char } - val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int] { + val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int]("Int") { def erasure = java.lang.Integer.TYPE - override def toString = "Int" override def newArray(len: Int): Array[Int] = new Array[Int](len) override def newWrappedArray(len: Int): WrappedArray[Int] = new WrappedArray.ofInt(new Array[Int](len)) override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt() private def readResolve(): Any = Manifest.Int } - val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long] { + val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long]("Long") { def erasure = java.lang.Long.TYPE - override def toString = "Long" override def newArray(len: Int): Array[Long] = new Array[Long](len) override def newWrappedArray(len: Int): WrappedArray[Long] = new WrappedArray.ofLong(new Array[Long](len)) override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong() private def readResolve(): Any = Manifest.Long } - val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float] { + val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float]("Float") { def erasure = java.lang.Float.TYPE - override def toString = "Float" override def newArray(len: Int): Array[Float] = new Array[Float](len) override def newWrappedArray(len: Int): WrappedArray[Float] = new WrappedArray.ofFloat(new Array[Float](len)) override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat() private def readResolve(): Any = Manifest.Float } - val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double] { + val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double]("Double") { def erasure = java.lang.Double.TYPE - override def toString = "Double" override def newArray(len: Int): Array[Double] = new Array[Double](len) override def newWrappedArray(len: Int): WrappedArray[Double] = new WrappedArray.ofDouble(new Array[Double](len)) override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble() private def readResolve(): Any = Manifest.Double } - val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean] { + val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean]("Boolean") { def erasure = java.lang.Boolean.TYPE - override def toString = "Boolean" override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) override def newWrappedArray(len: Int): WrappedArray[Boolean] = new WrappedArray.ofBoolean(new Array[Boolean](len)) override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean() private def readResolve(): Any = Manifest.Boolean } - val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit] { + val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit]("Unit") { def erasure = java.lang.Void.TYPE - override def toString = "Unit" override def newArray(len: Int): Array[Unit] = new Array[Unit](len) override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len)) override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit() private def readResolve(): Any = Manifest.Unit } - val Any: Manifest[Any] = new ClassTypeManifest[scala.Any](None, ObjectClass, Nil) { - override def toString = "Any" + val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any]("Any") { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.Any } - val Object: Manifest[Object] = new ClassTypeManifest[java.lang.Object](None, ObjectClass, Nil) { - override def toString = "Object" + val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object]("Object") { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.Object } - val AnyVal: Manifest[AnyVal] = new ClassTypeManifest[scala.AnyVal](None, ObjectClass, Nil) { - override def toString = "AnyVal" + val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal]("AnyVal") { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.AnyVal } - val Null: Manifest[Null] = new ClassTypeManifest[scala.Null](None, ObjectClass, Nil) { - override def toString = "Null" + val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null]("Null") { override def <:<(that: ClassManifest[_]): Boolean = (that ne null) && (that ne Nothing) && !(that <:< AnyVal) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.Null } - val Nothing: Manifest[Nothing] = new ClassTypeManifest[scala.Nothing](None, ObjectClass, Nil) { - override def toString = "Nothing" + val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing]("Nothing") { override def <:<(that: ClassManifest[_]): Boolean = (that ne null) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.Nothing } @@ -231,6 +208,11 @@ object Manifest { def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = new ClassTypeManifest[T](Some(prefix), clazz, args.toList) + private abstract class PhantomManifest[T](override val toString: String) extends ClassTypeManifest[T](None, classOf[java.lang.Object], Nil) { + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] + override val hashCode = System.identityHashCode(this) + } + /** Manifest for the class type `clazz[args]`, where `clazz` is * a top-level or static class. */ private class ClassTypeManifest[T](prefix: Option[Manifest[_]], diff --git a/src/library/scala/reflect/api/MacroContext.scala b/src/library/scala/reflect/api/MacroContext.scala new file mode 100644 index 0000000000..e23357d26e --- /dev/null +++ b/src/library/scala/reflect/api/MacroContext.scala @@ -0,0 +1,15 @@ +package scala.reflect +package api + +trait MacroContext extends Universe { + + /** Mark a variable as captured; i.e. force boxing in a *Ref type. + */ + def captureVariable(vble: Symbol): Unit + + /** Mark given identifier as a reference to a captured variable itself + * suppressing dereferencing with the `elem` field. + */ + def referenceCapturedVariable(id: Ident): Tree + +}
\ No newline at end of file diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 752319d9a4..2394925657 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -542,12 +542,18 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => case class Select(qualifier: Tree, name: Name) extends RefTree + def Select(qualifier: Tree, name: String): Select = + Select(qualifier, newTermName(name)) + def Select(qualifier: Tree, sym: Symbol): Select = Select(qualifier, sym.name) setSymbol sym /** Identifier <name> */ case class Ident(name: Name) extends RefTree { } + def Ident(name: String): Ident = + Ident(newTermName(name)) + def Ident(sym: Symbol): Ident = Ident(sym.name) setSymbol sym @@ -625,6 +631,11 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => def TypeTree(tp: Type): TypeTree = TypeTree() setType tp + /** An empty deferred value definition corresponding to: + * val _: _ + * This is used as a placeholder in the `self` parameter Template if there is + * no definition of a self value of self type. + */ def emptyValDef: ValDef // ------ traversers, copiers, and transformers --------------------------------------------- diff --git a/src/library/scala/runtime/AbstractPartialFunction.scala b/src/library/scala/runtime/AbstractPartialFunction.scala index f48d99f5af..cbe778f09b 100644 --- a/src/library/scala/runtime/AbstractPartialFunction.scala +++ b/src/library/scala/runtime/AbstractPartialFunction.scala @@ -26,7 +26,7 @@ abstract class AbstractPartialFunction[-T1, +R] private var fallBackField: PartialFunction[T1 @uncheckedVariance, R @uncheckedVariance] = _ def fallBack: PartialFunction[T1, R] = synchronized { - if (fallBackField == null) fallBackField = PartialFunction.empty + if (fallBackField eq null) fallBackField = PartialFunction.empty fallBackField } @@ -38,7 +38,7 @@ abstract class AbstractPartialFunction[-T1, +R] override def orElse[A1 <: T1, B1 >: R](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] = { val result = this.clone.asInstanceOf[AbstractPartialFunction[A1, B1]] result.synchronized { - result.fallBackField = this.fallBackField orElse that + result.fallBackField = if (this.fallBackField eq null) that else this.fallBackField orElse that result } } diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index c726c56d0e..b19c8d086c 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -769,6 +769,24 @@ public final class BoxesRunTime } throw new NoSuchMethodException(); } + + public static boolean isBoxedNumberOrBoolean(Object arg) { + if (arg instanceof java.lang.Boolean) + return true; + else + return isBoxedNumber(arg); + } + public static boolean isBoxedNumber(Object arg) { + return ( + (arg instanceof java.lang.Integer) + || (arg instanceof java.lang.Long) + || (arg instanceof java.lang.Double) + || (arg instanceof java.lang.Float) + || (arg instanceof java.lang.Short) + || (arg instanceof java.lang.Character) + || (arg instanceof java.lang.Byte) + ); + } /** arg.toChar */ public static java.lang.Character toCharacter(Object arg) throws NoSuchMethodException { diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index 998661895b..22de5544a8 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -142,6 +142,11 @@ private[scala] trait PropertiesTrait { */ def isWin = osName startsWith "Windows" def isMac = javaVendor startsWith "Apple" + + // This is looking for javac, tools.jar, etc. + // Tries JDK_HOME first, then the more common but likely jre JAVA_HOME, + // and finally the system property based javaHome. + def jdkHome = envOrElse("JDK_HOME", envOrElse("JAVA_HOME", javaHome)) def versionMsg = "Scala %s %s -- %s".format(propCategory, versionString, copyrightString) def scalaCmd = if (isWin) "scala.bat" else "scala" diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala index 751539243b..4004a01ad9 100644 --- a/src/library/scala/util/parsing/combinator/Parsers.scala +++ b/src/library/scala/util/parsing/combinator/Parsers.scala @@ -89,14 +89,14 @@ trait Parsers { sealed abstract class ParseResult[+T] { /** Functional composition of ParseResults. * - * @param `f` the function to be lifted over this result + * @param f the function to be lifted over this result * @return `f` applied to the result of this `ParseResult`, packaged up as a new `ParseResult` */ def map[U](f: T => U): ParseResult[U] /** Partial functional composition of ParseResults. * - * @param `f` the partial function to be lifted over this result + * @param f the partial function to be lifted over this result * @param error a function that takes the same argument as `f` and * produces an error message to explain why `f` wasn't applicable * (it is called when this is the case) @@ -240,7 +240,7 @@ trait Parsers { // no filter yet, dealing with zero is tricky! - @migration(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.") + @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") def append[U >: T](p0: => Parser[U]): Parser[U] = { lazy val p = p0 // lazy argument Parser{ in => this(in) append p(in)} } @@ -259,7 +259,7 @@ trait Parsers { * but easier to pattern match on) that contains the result of `p` and * that of `q`. The resulting parser fails if either `p` or `q` fails. */ - @migration(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.") + @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") def ~ [U](q: => Parser[U]): Parser[~[T, U]] = { lazy val p = q // lazy argument (for(a <- this; b <- p) yield new ~(a,b)).named("~") } @@ -272,7 +272,7 @@ trait Parsers { * succeeds -- evaluated at most once, and only when necessary. * @return a `Parser` that -- on success -- returns the result of `q`. */ - @migration(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.") + @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") def ~> [U](q: => Parser[U]): Parser[U] = { lazy val p = q // lazy argument (for(a <- this; b <- p) yield b).named("~>") } @@ -287,7 +287,7 @@ trait Parsers { * @param q a parser that will be executed after `p` (this parser) succeeds -- evaluated at most once, and only when necessary * @return a `Parser` that -- on success -- returns the result of `p`. */ - @migration(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.") + @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") def <~ [U](q: => Parser[U]): Parser[T] = { lazy val p = q // lazy argument (for(a <- this; b <- p) yield a).named("<~") } @@ -302,7 +302,7 @@ trait Parsers { * `p ~! q` succeeds if `p` succeeds and `q` succeeds on the input left over by `p`. * In case of failure, no back-tracking is performed (in an earlier parser produced by the `|` combinator). * - * @param q a parser that will be executed after `p` (this parser) succeeds + * @param p a parser that will be executed after `p` (this parser) succeeds * @return a `Parser` that -- on success -- returns a `~` (like a Pair, but easier to pattern match on) * that contains the result of `p` and that of `q`. * The resulting parser fails if either `p` or `q` fails, this failure is fatal. @@ -332,7 +332,7 @@ trait Parsers { * @param q0 a parser that accepts if p consumes less characters. -- evaluated at most once, and only when necessary * @return a `Parser` that returns the result of the parser consuming the most characters (out of `p` and `q`). */ - @migration(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.") + @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") def ||| [U >: T](q0: => Parser[U]): Parser[U] = new Parser[U] { lazy val q = q0 // lazy argument def apply(in: Input) = { @@ -367,7 +367,7 @@ trait Parsers { * @param v The new result for the parser, evaluated at most once (if `p` succeeds), not evaluated at all if `p` fails. * @return a parser that has the same behaviour as the current parser, but whose successful result is `v` */ - @migration(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.") + @migration("The call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") def ^^^ [U](v: => U): Parser[U] = new Parser[U] { lazy val v0 = v // lazy argument def apply(in: Input) = Parser.this(in) map (x => v0) @@ -706,7 +706,7 @@ trait Parsers { * @return A parser that returns a list of results produced by first applying `f` and then * repeatedly `p` to the input (it only succeeds if `f` matches). */ - @migration(2, 9, "As of 2.9, the p0 call-by-name arguments is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.") + @migration("The `p0` call-by-name arguments is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.", "2.9.0") def rep1[T](first: => Parser[T], p0: => Parser[T]): Parser[List[T]] = Parser { in => lazy val p = p0 // lazy argument val elems = new ListBuffer[T] @@ -733,9 +733,9 @@ trait Parsers { * `repN(n, p)` uses `p` exactly `n` time to parse the input * (the result is a `List` of the `n` consecutive results of `p`). * - * @param p a `Parser` that is to be applied successively to the input - * @param n the exact number of times `p` must succeed - * @return A parser that returns a list of results produced by repeatedly applying `p` to the input + * @param p a `Parser` that is to be applied successively to the input + * @param num the exact number of times `p` must succeed + * @return A parser that returns a list of results produced by repeatedly applying `p` to the input * (and that only succeeds if `p` matches exactly `n` times). */ def repN[T](num: Int, p: => Parser[T]): Parser[List[T]] = diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala index 127e6e0ab7..df52b34f87 100644 --- a/src/library/scala/xml/Elem.scala +++ b/src/library/scala/xml/Elem.scala @@ -41,7 +41,7 @@ object Elem { class Elem( override val prefix: String, val label: String, - override val attributes: MetaData, + attributes1: MetaData, override val scope: NamespaceBinding, val child: Node*) extends Node with Serializable @@ -49,6 +49,8 @@ extends Node with Serializable final override def doCollectNamespaces = true final override def doTransform = true + override val attributes = MetaData.normalize(attributes1, scope) + if (prefix == "") throw new IllegalArgumentException("prefix of zero length, use null instead") diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala index 98e863eb37..c516747bae 100644 --- a/src/library/scala/xml/MetaData.scala +++ b/src/library/scala/xml/MetaData.scala @@ -38,8 +38,8 @@ object MetaData { def iterate(md: MetaData, normalized_attribs: MetaData, set: Set[String]): MetaData = { lazy val key = getUniversalKey(md, scope) if (md eq Null) normalized_attribs - else if (set(key)) iterate(md.next, normalized_attribs, set) - else iterate(md.next, md copy normalized_attribs, set + key) + else if ((md.value eq null) || set(key)) iterate(md.next, normalized_attribs, set) + else md copy iterate(md.next, normalized_attribs, set + key) } iterate(attribs, Null, Set()) } diff --git a/src/library/scala/xml/PrefixedAttribute.scala b/src/library/scala/xml/PrefixedAttribute.scala index 436dfcda43..b80d6a1c73 100644 --- a/src/library/scala/xml/PrefixedAttribute.scala +++ b/src/library/scala/xml/PrefixedAttribute.scala @@ -13,22 +13,25 @@ package scala.xml * * @param pre ... * @param key ... - * @param value the attribute value, which may not be null + * @param value the attribute value * @param next ... */ class PrefixedAttribute( val pre: String, val key: String, val value: Seq[Node], - val next: MetaData) + val next1: MetaData) extends Attribute { - if (value eq null) - throw new UnsupportedOperationException("value is null") + val next = if (value ne null) next1 else next1.remove(key) - /** same as this(key, Utility.parseAttributeValue(value), next) */ + /** same as this(pre, key, Text(value), next), or no attribute if value is null */ def this(pre: String, key: String, value: String, next: MetaData) = - this(pre, key, Text(value), next) + this(pre, key, if (value ne null) Text(value) else null: NodeSeq, next) + + /** same as this(pre, key, value.get, next), or no attribute if value is None */ + def this(pre: String, key: String, value: Option[Seq[Node]], next: MetaData) = + this(pre, key, value.orNull, next) /** Returns a copy of this unprefixed attribute with the given * next field. diff --git a/src/library/scala/xml/UnprefixedAttribute.scala b/src/library/scala/xml/UnprefixedAttribute.scala index c56fba1e6c..b6800d5ed1 100644 --- a/src/library/scala/xml/UnprefixedAttribute.scala +++ b/src/library/scala/xml/UnprefixedAttribute.scala @@ -22,7 +22,7 @@ extends Attribute final val pre = null val next = if (value ne null) next1 else next1.remove(key) - /** same as this(key, Text(value), next) */ + /** same as this(key, Text(value), next), or no attribute if value is null */ def this(key: String, value: String, next: MetaData) = this(key, if (value ne null) Text(value) else null: NodeSeq, next) diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index 9b48f4e1bb..fc20b892b9 100644 --- a/src/library/scala/xml/Utility.scala +++ b/src/library/scala/xml/Utility.scala @@ -61,7 +61,7 @@ object Utility extends AnyRef with parsing.TokenTests { val key = md.key val smaller = sort(md.filter { m => m.key < key }) val greater = sort(md.filter { m => m.key > key }) - smaller.append( Null ).append(md.copy ( greater )) + smaller.copy(md.copy ( greater )) } /** Return the node with its attribute list sorted alphabetically |