summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authoraleksandar <aleksandar@lampmac14.epfl.ch>2012-01-12 15:04:04 +0100
committeraleksandar <aleksandar@lampmac14.epfl.ch>2012-01-12 15:04:04 +0100
commitaa568432a102287881a2a524f340926c1698165b (patch)
tree76daa35c30ac692e204d0e2314b475521397251c /src/library
parentd43d5e5e22e61061cd84ab8b69b237249a519994 (diff)
parent986bbb0914bde62978b18a3dc395b45e993a5812 (diff)
downloadscala-aa568432a102287881a2a524f340926c1698165b.tar.gz
scala-aa568432a102287881a2a524f340926c1698165b.tar.bz2
scala-aa568432a102287881a2a524f340926c1698165b.zip
Merge branch 'execution-context' of github.com:phaller/scala into execution-context
Conflicts: .gitignore
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/Either.scala8
-rw-r--r--src/library/scala/Enumeration.scala35
-rw-r--r--src/library/scala/MatchingStrategy.scala23
-rw-r--r--src/library/scala/Option.scala7
-rw-r--r--src/library/scala/Symbol.scala4
-rw-r--r--src/library/scala/annotation/migration.scala18
-rw-r--r--src/library/scala/collection/GenTraversableLike.scala5
-rw-r--r--src/library/scala/collection/GenTraversableViewLike.scala2
-rw-r--r--src/library/scala/collection/Iterator.scala17
-rw-r--r--src/library/scala/collection/LinearSeqLike.scala6
-rw-r--r--src/library/scala/collection/MapLike.scala4
-rw-r--r--src/library/scala/collection/SetLike.scala2
-rw-r--r--src/library/scala/collection/TraversableLike.scala5
-rw-r--r--src/library/scala/collection/TraversableViewLike.scala11
-rw-r--r--src/library/scala/collection/generic/GenericTraversableTemplate.scala3
-rw-r--r--src/library/scala/collection/immutable/List.scala247
-rw-r--r--src/library/scala/collection/immutable/Map.scala1
-rw-r--r--src/library/scala/collection/immutable/Range.scala122
-rw-r--r--src/library/scala/collection/mutable/BufferLike.scala22
-rw-r--r--src/library/scala/collection/mutable/DoubleLinkedListLike.scala2
-rw-r--r--src/library/scala/collection/mutable/FlatHashTable.scala99
-rw-r--r--src/library/scala/collection/mutable/ImmutableMapAdaptor.scala4
-rw-r--r--src/library/scala/collection/mutable/MapLike.scala30
-rw-r--r--src/library/scala/collection/mutable/PriorityQueue.scala2
-rw-r--r--src/library/scala/collection/mutable/SetLike.scala30
-rw-r--r--src/library/scala/collection/mutable/Stack.scala6
-rw-r--r--src/library/scala/collection/mutable/StringBuilder.scala2
-rw-r--r--src/library/scala/collection/mutable/SynchronizedMap.scala4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParRange.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashMap.scala5
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashSet.scala13
-rw-r--r--src/library/scala/concurrent/Future.scala16
-rw-r--r--src/library/scala/io/Codec.scala21
-rw-r--r--src/library/scala/math/BigDecimal.scala1
-rw-r--r--src/library/scala/math/Ordered.scala4
-rw-r--r--src/library/scala/math/Ordering.scala42
-rw-r--r--src/library/scala/reflect/ClassManifest.scala4
-rw-r--r--src/library/scala/reflect/Manifest.scala66
-rw-r--r--src/library/scala/reflect/api/MacroContext.scala15
-rw-r--r--src/library/scala/reflect/api/Trees.scala11
-rw-r--r--src/library/scala/runtime/AbstractPartialFunction.scala4
-rw-r--r--src/library/scala/runtime/BoxesRunTime.java18
-rw-r--r--src/library/scala/util/Properties.scala5
-rw-r--r--src/library/scala/util/parsing/combinator/Parsers.scala26
-rw-r--r--src/library/scala/xml/Elem.scala4
-rw-r--r--src/library/scala/xml/MetaData.scala4
-rw-r--r--src/library/scala/xml/PrefixedAttribute.scala15
-rw-r--r--src/library/scala/xml/UnprefixedAttribute.scala2
-rw-r--r--src/library/scala/xml/Utility.scala2
49 files changed, 684 insertions, 317 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>) &amp;&amp;
+ * ... &amp;&amp; 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 &amp;&amp; (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/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index dff1adb45c..bb1612876c 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -65,16 +65,17 @@ self =>
/* Callbacks */
/** When this future is completed successfully (i.e. with a value),
- * apply the provided function to the value.
+ * apply the provided partial function to the value if the partial function
+ * is defined at that value.
*
* If the future has already been completed with a value,
* this will either be applied immediately or be scheduled asynchronously.
*
* $multipleCallbacks
*/
- def onSuccess[U](func: T => U): this.type = onComplete {
+ def onSuccess[U](pf: PartialFunction[T, U]): this.type = onComplete {
case Left(t) => // do nothing
- case Right(v) => func(v)
+ case Right(v) if pf isDefinedAt v => pf(v)
}
/** When this future is completed with a failure (i.e. with a throwable),
@@ -243,11 +244,12 @@ self =>
/** Asynchronously processes the value in the future once the value becomes available.
*
- * Will not be called if the future times out or fails.
- *
- * This method typically registers an `onSuccess` callback.
+ * Will not be called if the future fails.
*/
- def foreach[U](f: T => U): Unit = onSuccess(f)
+ def foreach[U](f: T => U): Unit = onComplete {
+ case Right(r) => f(r)
+ case Left(_) => // do nothing
+ }
/** Creates a new future by applying a function to the successful result of
* this future. If this future is completed with an exception then the new
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