diff options
42 files changed, 346 insertions, 280 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Modes.scala b/src/compiler/scala/tools/nsc/typechecker/Modes.scala index bde3ad98c9..3eff5ef024 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Modes.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Modes.scala @@ -86,10 +86,6 @@ trait Modes { */ final val TYPEPATmode = 0x10000 - /** RETmode is set when we are typing a return expression. - */ - final val RETmode = 0x20000 - final private val StickyModes = EXPRmode | PATTERNmode | TYPEmode | ALTmode final def onlyStickyModes(mode: Int) = diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 688c842637..d251109dc4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4024,8 +4024,7 @@ trait Typers extends Modes with Adaptations with Tags { ReturnWithoutTypeError(tree, enclMethod.owner) } else { context.enclMethod.returnsSeen = true - val expr1: Tree = typed(expr, EXPRmode | BYVALmode | RETmode, restpt.tpe) - + val expr1: Tree = typed(expr, EXPRmode | BYVALmode, restpt.tpe) // Warn about returning a value if no value can be returned. if (restpt.tpe.typeSymbol == UnitClass) { // The typing in expr1 says expr is Unit (it has already been coerced if diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala index 464ffc6fab..a20ff1667b 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala @@ -171,9 +171,6 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { vprintln("yes we can!! (byval)") return true } - } else if ((mode & global.analyzer.RETmode) != 0) { - vprintln("yes we can!! (return)") - return true } } false @@ -187,7 +184,6 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { val patMode = (mode & global.analyzer.PATTERNmode) != 0 val exprMode = (mode & global.analyzer.EXPRmode) != 0 val byValMode = (mode & global.analyzer.BYVALmode) != 0 - val retMode = (mode & global.analyzer.RETmode) != 0 val annotsTree = cpsParamAnnotation(tree.tpe) val annotsExpected = cpsParamAnnotation(pt) @@ -214,12 +210,6 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { val res = tree modifyType addMinusMarker vprintln("adapted annotations (by val) of " + tree + " to " + res.tpe) res - } else if (retMode && !hasPlusMarker(tree.tpe) && annotsTree.isEmpty && annotsExpected.nonEmpty) { - // add a marker annotation that will make tree.tpe behave as pt, subtyping wise - // tree will look like having no annotation - val res = tree modifyType (_ withAnnotations List(newPlusMarker())) - vprintln("adapted annotations (return) of " + tree + " to " + res.tpe) - res } else tree } @@ -476,11 +466,6 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { } tpe - case ret @ Return(expr) => - if (hasPlusMarker(expr.tpe)) - ret setType expr.tpe - ret.tpe - case _ => tpe } diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala index 765cde5a81..3a1dc87a6a 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala @@ -3,7 +3,6 @@ package scala.tools.selectivecps import scala.tools.nsc.Global -import scala.collection.mutable.ListBuffer trait CPSUtils { val global: Global @@ -136,43 +135,4 @@ trait CPSUtils { case _ => None } } - - def isTailReturn(retExpr: Tree, body: Tree): Boolean = { - val removed = ListBuffer[Tree]() - removeTailReturn(body, removed) - removed contains retExpr - } - - def removeTailReturn(tree: Tree, removed: ListBuffer[Tree]): Tree = tree match { - case Block(stms, r @ Return(expr)) => - removed += r - treeCopy.Block(tree, stms, expr) - - case Block(stms, expr) => - treeCopy.Block(tree, stms, removeTailReturn(expr, removed)) - - case If(cond, r1 @ Return(thenExpr), r2 @ Return(elseExpr)) => - removed ++= Seq(r1, r2) - treeCopy.If(tree, cond, removeTailReturn(thenExpr, removed), removeTailReturn(elseExpr, removed)) - - case If(cond, thenExpr, elseExpr) => - treeCopy.If(tree, cond, removeTailReturn(thenExpr, removed), removeTailReturn(elseExpr, removed)) - - case Try(block, catches, finalizer) => - treeCopy.Try(tree, - removeTailReturn(block, removed), - (catches map (t => removeTailReturn(t, removed))).asInstanceOf[List[CaseDef]], - removeTailReturn(finalizer, removed)) - - case CaseDef(pat, guard, r @ Return(expr)) => - removed += r - treeCopy.CaseDef(tree, pat, guard, expr) - - case CaseDef(pat, guard, body) => - treeCopy.CaseDef(tree, pat, guard, removeTailReturn(body, removed)) - - case _ => - tree - } - } diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index fe465aad0d..017c8d24fd 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -9,8 +9,6 @@ import scala.tools.nsc.plugins._ import scala.tools.nsc.ast._ -import scala.collection.mutable.ListBuffer - /** * In methods marked @cps, explicitly name results of calls to other @cps methods */ @@ -48,20 +46,10 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with // this would cause infinite recursion. But we could remove the // ValDef case here. - case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs0) => + case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) => debuglog("transforming " + dd.symbol) atOwner(dd.symbol) { - val tailReturns = ListBuffer[Tree]() - val rhs = removeTailReturn(rhs0, tailReturns) - // throw an error if there is a Return tree which is not in tail position - rhs0 foreach { - case r @ Return(_) => - if (!tailReturns.contains(r)) - unit.error(r.pos, "return expressions in CPS code must be in tail position") - case _ => /* do nothing */ - } - val rhs1 = transExpr(rhs, None, getExternalAnswerTypeAnn(tpt.tpe)) debuglog("result "+rhs1) @@ -165,6 +153,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with } } + def transExpr(tree: Tree, cpsA: CPSInfo, cpsR: CPSInfo): Tree = { transTailValue(tree, cpsA, cpsR) match { case (Nil, b) => b diff --git a/src/library/scala/collection/DefaultMap.scala b/src/library/scala/collection/DefaultMap.scala index d00414751a..d961bd84bb 100644 --- a/src/library/scala/collection/DefaultMap.scala +++ b/src/library/scala/collection/DefaultMap.scala @@ -27,7 +27,7 @@ import generic._ * @since 2.8 */ trait DefaultMap[A, +B] extends Map[A, B] { self => - + /** A default implementation which creates a new immutable map. */ override def +[B1 >: B](kv: (A, B1)): Map[A, B1] = { @@ -41,7 +41,7 @@ trait DefaultMap[A, +B] extends Map[A, B] { self => */ override def - (key: A): Map[A, B] = { val b = newBuilder - b ++= this filter (key != _) + b ++= this filter (key != _._1) b.result } } diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala index e475865391..25edcfe19c 100644 --- a/src/library/scala/collection/GenTraversableOnce.scala +++ b/src/library/scala/collection/GenTraversableOnce.scala @@ -565,10 +565,10 @@ trait GenTraversableOnce[+A] extends Any { * @tparam Col The collection type to build. * @return a new collection containing all elements of this $coll. * - * @usecase def convertTo[Col[_]]: Col[A] + * @usecase def to[Col[_]]: Col[A] * @inheritdoc * $willNotTerminateInf * @return a new collection containing all elements of this $coll. */ - def convertTo[Col[_]](implicit cbf: CanBuildFrom[Nothing, A, Col[A @uV]]): Col[A @uV] + def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, A, Col[A @uV]]): Col[A @uV] } diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala index 42a56a9c5a..19c24c9791 100644 --- a/src/library/scala/collection/Map.scala +++ b/src/library/scala/collection/Map.scala @@ -51,6 +51,7 @@ object Map extends MapFactory[Map] { def iterator = underlying.iterator override def default(key: A): B = d(key) } + } /** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */ diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala index 75f9ff93db..55d482f6c8 100644 --- a/src/library/scala/collection/MapLike.scala +++ b/src/library/scala/collection/MapLike.scala @@ -226,7 +226,7 @@ self => */ def default(key: A): B = throw new NoSuchElementException("key not found: " + key) - + protected class FilteredKeys(p: A => Boolean) extends AbstractMap[A, B] with DefaultMap[A, B] { override def foreach[C](f: ((A, B)) => C): Unit = for (kv <- self) if (p(kv._1)) f(kv) def iterator = self.iterator.filter(kv => p(kv._1)) @@ -240,7 +240,7 @@ self => * the predicate `p`. The resulting map wraps the original map without copying any elements. */ def filterKeys(p: A => Boolean): Map[A, B] = new FilteredKeys(p) - + protected class MappedValues[C](f: B => C) extends AbstractMap[A, C] with DefaultMap[A, C] { override def foreach[D](g: ((A, C)) => D): Unit = for ((k, v) <- self) g((k, f(v))) def iterator = for ((k, v) <- self.iterator) yield (k, f(v)) diff --git a/src/library/scala/collection/SortedMap.scala b/src/library/scala/collection/SortedMap.scala index 3f92908848..e32e0977df 100644 --- a/src/library/scala/collection/SortedMap.scala +++ b/src/library/scala/collection/SortedMap.scala @@ -30,9 +30,26 @@ trait SortedMap[A, +B] extends Map[A, B] with SortedMapLike[A, B, SortedMap[A, B * @since 2.8 */ object SortedMap extends SortedMapFactory[SortedMap] { - def empty[A, B](implicit ord: Ordering[A]): immutable.SortedMap[A, B] = immutable.SortedMap.empty[A, B](ord) + def empty[A, B](implicit ord: Ordering[A]): SortedMap[A, B] = immutable.SortedMap.empty[A, B](ord) implicit def canBuildFrom[A, B](implicit ord: Ordering[A]): CanBuildFrom[Coll, (A, B), SortedMap[A, B]] = new SortedMapCanBuildFrom[A, B] + + private[collection] trait Default[A, +B] extends SortedMap[A, B] { + self => + override def +[B1 >: B](kv: (A, B1)): SortedMap[A, B1] = { + val b = SortedMap.newBuilder[A, B1] + b ++= this + b += ((kv._1, kv._2)) + b.result + } + + override def - (key: A): SortedMap[A, B] = { + val b = newBuilder + for (kv <- this; if kv._1 != key) b += kv + b.result + } + } + } diff --git a/src/library/scala/collection/SortedMapLike.scala b/src/library/scala/collection/SortedMapLike.scala index 4dc0820a62..f9e95230ea 100644 --- a/src/library/scala/collection/SortedMapLike.scala +++ b/src/library/scala/collection/SortedMapLike.scala @@ -72,4 +72,27 @@ self => for (e <- elems) m = m + e m } + + override def filterKeys(p: A => Boolean): SortedMap[A, B] = new FilteredKeys(p) with SortedMap.Default[A, B] { + implicit def ordering: Ordering[A] = self.ordering + override def rangeImpl(from : Option[A], until : Option[A]): SortedMap[A, B] = self.rangeImpl(from, until).filterKeys(p) + } + + override def mapValues[C](f: B => C): SortedMap[A, C] = new MappedValues(f) with SortedMap.Default[A, C] { + implicit def ordering: Ordering[A] = self.ordering + override def rangeImpl(from : Option[A], until : Option[A]): SortedMap[A, C] = self.rangeImpl(from, until).mapValues(f) + } + + /** Adds a number of elements provided by a traversable object + * and returns a new collection with the added elements. + * + * @param xs the traversable object. + */ + override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): SortedMap[A, B1] = + ((repr: SortedMap[A, B1]) /: xs.seq) (_ + _) + } + + + + diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index e5861f5760..9356832afd 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -617,7 +617,7 @@ trait TraversableLike[+A, +Repr] extends Any def toIterator: Iterator[A] = toStream.iterator def toStream: Stream[A] = toBuffer.toStream // Override to provide size hint. - override def convertTo[Col[_]](implicit cbf: CanBuildFrom[Nothing, A, Col[A @uV]]): Col[A @uV] = { + override def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, A, Col[A @uV]]): Col[A @uV] = { val b = cbf() b.sizeHint(this) b ++= thisCollection diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala index 8dc6184d88..fb73805cc5 100644 --- a/src/library/scala/collection/TraversableOnce.scala +++ b/src/library/scala/collection/TraversableOnce.scala @@ -240,21 +240,21 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { def toTraversable: Traversable[A] - def toList: List[A] = convertTo[List] + def toList: List[A] = to[List] def toIterable: Iterable[A] = toStream def toSeq: Seq[A] = toStream - def toIndexedSeq: immutable.IndexedSeq[A] = convertTo[immutable.IndexedSeq] + def toIndexedSeq: immutable.IndexedSeq[A] = to[immutable.IndexedSeq] - def toBuffer[B >: A]: mutable.Buffer[B] = convertTo[ArrayBuffer].asInstanceOf[mutable.Buffer[B]] + def toBuffer[B >: A]: mutable.Buffer[B] = to[ArrayBuffer].asInstanceOf[mutable.Buffer[B]] - def toSet[B >: A]: immutable.Set[B] = convertTo[immutable.Set].asInstanceOf[immutable.Set[B]] + def toSet[B >: A]: immutable.Set[B] = to[immutable.Set].asInstanceOf[immutable.Set[B]] - def toVector: Vector[A] = convertTo[Vector] + def toVector: Vector[A] = to[Vector] - def convertTo[Col[_]](implicit cbf: CanBuildFrom[Nothing, A, Col[A @uV]]): Col[A @uV] = { + def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, A, Col[A @uV]]): Col[A @uV] = { val b = cbf() b ++= seq b.result diff --git a/src/library/scala/collection/immutable/MapLike.scala b/src/library/scala/collection/immutable/MapLike.scala index 6ae2d78188..2dc08fff24 100644 --- a/src/library/scala/collection/immutable/MapLike.scala +++ b/src/library/scala/collection/immutable/MapLike.scala @@ -48,7 +48,8 @@ import parallel.immutable.ParMap trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] extends scala.collection.MapLike[A, B, This] with Parallelizable[(A, B), ParMap[A, B]] -{ self => +{ +self => protected[this] override def parCombiner = ParMap.newCombiner[A, B] @@ -84,31 +85,20 @@ trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] */ override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): immutable.Map[A, B1] = ((repr: immutable.Map[A, B1]) /: xs.seq) (_ + _) - + /** Filters this map by retaining only keys satisfying a predicate. * @param p the predicate used to test keys * @return an immutable map consisting only of those key value pairs of this map where the key satisfies * the predicate `p`. The resulting map wraps the original map without copying any elements. */ - override def filterKeys(p: A => Boolean): Map[A, B] = new AbstractMap[A, B] with DefaultMap[A, B] { - override def foreach[C](f: ((A, B)) => C): Unit = for (kv <- self) if (p(kv._1)) f(kv) - def iterator = self.iterator.filter(kv => p(kv._1)) - override def contains(key: A) = self.contains(key) && p(key) - def get(key: A) = if (!p(key)) None else self.get(key) - } - + override def filterKeys(p: A => Boolean): Map[A, B] = new FilteredKeys(p) with DefaultMap[A, B] + /** Transforms this map by applying a function to every retrieved value. * @param f the function used to transform values of this map. * @return a map view which maps every key of this map * to `f(this(key))`. The resulting map wraps the original map without copying any elements. */ - override def mapValues[C](f: B => C): Map[A, C] = new AbstractMap[A, C] with DefaultMap[A, C] { - override def foreach[D](g: ((A, C)) => D): Unit = for ((k, v) <- self) g((k, f(v))) - def iterator = for ((k, v) <- self.iterator) yield (k, f(v)) - override def size = self.size - override def contains(key: A) = self.contains(key) - def get(key: A) = self.get(key).map(f) - } + override def mapValues[C](f: B => C): Map[A, C] = new MappedValues(f) with DefaultMap[A, C] /** Collects all keys of this map in a set. * @return a set containing all keys of this map. diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala index 0f28c4997b..4b573511d1 100644 --- a/src/library/scala/collection/immutable/RedBlackTree.scala +++ b/src/library/scala/collection/immutable/RedBlackTree.scala @@ -43,7 +43,7 @@ object RedBlackTree { } def count(tree: Tree[_, _]) = if (tree eq null) 0 else tree.count - def update[A, B, B1 >: B](tree: Tree[A, B], k: A, v: B1)(implicit ordering: Ordering[A]): Tree[A, B1] = blacken(upd(tree, k, v)) + def update[A, B, B1 >: B](tree: Tree[A, B], k: A, v: B1, overwrite: Boolean)(implicit ordering: Ordering[A]): Tree[A, B1] = blacken(upd(tree, k, v, overwrite)) def delete[A, B](tree: Tree[A, B], k: A)(implicit ordering: Ordering[A]): Tree[A, B] = blacken(del(tree, k)) def rangeImpl[A: Ordering, B](tree: Tree[A, B], from: Option[A], until: Option[A]): Tree[A, B] = (from, until) match { case (Some(from), Some(until)) => this.range(tree, from, until) @@ -122,17 +122,18 @@ object RedBlackTree { else mkTree(isBlack, x, xv, a, r) } - private[this] def upd[A, B, B1 >: B](tree: Tree[A, B], k: A, v: B1)(implicit ordering: Ordering[A]): Tree[A, B1] = if (tree eq null) { + private[this] def upd[A, B, B1 >: B](tree: Tree[A, B], k: A, v: B1, overwrite: Boolean)(implicit ordering: Ordering[A]): Tree[A, B1] = if (tree eq null) { RedTree(k, v, null, null) } else { val cmp = ordering.compare(k, tree.key) - if (cmp < 0) balanceLeft(isBlackTree(tree), tree.key, tree.value, upd(tree.left, k, v), tree.right) - else if (cmp > 0) balanceRight(isBlackTree(tree), tree.key, tree.value, tree.left, upd(tree.right, k, v)) - else mkTree(isBlackTree(tree), k, v, tree.left, tree.right) + if (cmp < 0) balanceLeft(isBlackTree(tree), tree.key, tree.value, upd(tree.left, k, v, overwrite), tree.right) + else if (cmp > 0) balanceRight(isBlackTree(tree), tree.key, tree.value, tree.left, upd(tree.right, k, v, overwrite)) + else if (overwrite || k != tree.key) mkTree(isBlackTree(tree), k, v, tree.left, tree.right) + else tree } - // Based on Stefan Kahrs' Haskell version of Okasaki's Red&Black Trees - // http://www.cse.unsw.edu.au/~dons/data/RedBlackTree.html + /* Based on Stefan Kahrs' Haskell version of Okasaki's Red&Black Trees + * http://www.cse.unsw.edu.au/~dons/data/RedBlackTree.html */ private[this] def del[A, B](tree: Tree[A, B], k: A)(implicit ordering: Ordering[A]): Tree[A, B] = if (tree eq null) null else { def balance(x: A, xv: B, tl: Tree[A, B], tr: Tree[A, B]) = if (isRedTree(tl)) { if (isRedTree(tr)) { @@ -216,7 +217,7 @@ object RedBlackTree { if (ordering.lt(tree.key, from)) return doFrom(tree.right, from) val newLeft = doFrom(tree.left, from) if (newLeft eq tree.left) tree - else if (newLeft eq null) upd(tree.right, tree.key, tree.value) + else if (newLeft eq null) upd(tree.right, tree.key, tree.value, false) else rebalance(tree, newLeft, tree.right) } private[this] def doTo[A, B](tree: Tree[A, B], to: A)(implicit ordering: Ordering[A]): Tree[A, B] = { @@ -224,7 +225,7 @@ object RedBlackTree { if (ordering.lt(to, tree.key)) return doTo(tree.left, to) val newRight = doTo(tree.right, to) if (newRight eq tree.right) tree - else if (newRight eq null) upd(tree.left, tree.key, tree.value) + else if (newRight eq null) upd(tree.left, tree.key, tree.value, false) else rebalance(tree, tree.left, newRight) } private[this] def doUntil[A, B](tree: Tree[A, B], until: A)(implicit ordering: Ordering[A]): Tree[A, B] = { @@ -232,7 +233,7 @@ object RedBlackTree { if (ordering.lteq(until, tree.key)) return doUntil(tree.left, until) val newRight = doUntil(tree.right, until) if (newRight eq tree.right) tree - else if (newRight eq null) upd(tree.left, tree.key, tree.value) + else if (newRight eq null) upd(tree.left, tree.key, tree.value, false) else rebalance(tree, tree.left, newRight) } private[this] def doRange[A, B](tree: Tree[A, B], from: A, until: A)(implicit ordering: Ordering[A]): Tree[A, B] = { @@ -242,8 +243,8 @@ object RedBlackTree { val newLeft = doFrom(tree.left, from) val newRight = doUntil(tree.right, until) if ((newLeft eq tree.left) && (newRight eq tree.right)) tree - else if (newLeft eq null) upd(newRight, tree.key, tree.value); - else if (newRight eq null) upd(newLeft, tree.key, tree.value); + else if (newLeft eq null) upd(newRight, tree.key, tree.value, false); + else if (newRight eq null) upd(newLeft, tree.key, tree.value, false); else rebalance(tree, newLeft, newRight) } @@ -254,7 +255,7 @@ object RedBlackTree { if (n > count) return doDrop(tree.right, n - count - 1) val newLeft = doDrop(tree.left, n) if (newLeft eq tree.left) tree - else if (newLeft eq null) upd(tree.right, tree.key, tree.value) + else if (newLeft eq null) upd(tree.right, tree.key, tree.value, false) else rebalance(tree, newLeft, tree.right) } private[this] def doTake[A: Ordering, B](tree: Tree[A, B], n: Int): Tree[A, B] = { @@ -264,7 +265,7 @@ object RedBlackTree { if (n <= count) return doTake(tree.left, n) val newRight = doTake(tree.right, n - count - 1) if (newRight eq tree.right) tree - else if (newRight eq null) upd(tree.left, tree.key, tree.value) + else if (newRight eq null) upd(tree.left, tree.key, tree.value, false) else rebalance(tree, tree.left, newRight) } private[this] def doSlice[A: Ordering, B](tree: Tree[A, B], from: Int, until: Int): Tree[A, B] = { @@ -275,8 +276,8 @@ object RedBlackTree { val newLeft = doDrop(tree.left, from) val newRight = doTake(tree.right, until - count - 1) if ((newLeft eq tree.left) && (newRight eq tree.right)) tree - else if (newLeft eq null) upd(newRight, tree.key, tree.value) - else if (newRight eq null) upd(newLeft, tree.key, tree.value) + else if (newLeft eq null) upd(newRight, tree.key, tree.value, false) + else if (newRight eq null) upd(newLeft, tree.key, tree.value, false) else rebalance(tree, newLeft, newRight) } diff --git a/src/library/scala/collection/immutable/SortedMap.scala b/src/library/scala/collection/immutable/SortedMap.scala index 526f7a1ffe..f147b673f7 100644 --- a/src/library/scala/collection/immutable/SortedMap.scala +++ b/src/library/scala/collection/immutable/SortedMap.scala @@ -30,7 +30,9 @@ import annotation.unchecked.uncheckedVariance trait SortedMap[A, +B] extends Map[A, B] with scala.collection.SortedMap[A, B] with MapLike[A, B, SortedMap[A, B]] - with SortedMapLike[A, B, SortedMap[A, B]] { self => + with SortedMapLike[A, B, SortedMap[A, B]] +{ +self => override protected[this] def newBuilder : Builder[(A, B), SortedMap[A, B]] = SortedMap.newBuilder[A, B] @@ -76,6 +78,17 @@ trait SortedMap[A, +B] extends Map[A, B] */ override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): SortedMap[A, B1] = ((repr: SortedMap[A, B1]) /: xs.seq) (_ + _) + + override def filterKeys(p: A => Boolean): SortedMap[A, B] = new FilteredKeys(p) with SortedMap.Default[A, B] { + implicit def ordering: Ordering[A] = self.ordering + override def rangeImpl(from : Option[A], until : Option[A]): SortedMap[A, B] = self.rangeImpl(from, until).filterKeys(p) + } + + override def mapValues[C](f: B => C): SortedMap[A, C] = new MappedValues(f) with SortedMap.Default[A, C] { + implicit def ordering: Ordering[A] = self.ordering + override def rangeImpl(from : Option[A], until : Option[A]): SortedMap[A, C] = self.rangeImpl(from, until).mapValues(f) + } + } /** $factoryInfo @@ -86,4 +99,20 @@ object SortedMap extends ImmutableSortedMapFactory[SortedMap] { /** $sortedMapCanBuildFromInfo */ implicit def canBuildFrom[A, B](implicit ord: Ordering[A]): CanBuildFrom[Coll, (A, B), SortedMap[A, B]] = new SortedMapCanBuildFrom[A, B] def empty[A, B](implicit ord: Ordering[A]): SortedMap[A, B] = TreeMap.empty[A, B] + + private[collection] trait Default[A, +B] extends SortedMap[A, B] with collection.SortedMap.Default[A, B] { + self => + override def +[B1 >: B](kv: (A, B1)): SortedMap[A, B1] = { + val b = SortedMap.newBuilder[A, B1] + b ++= this + b += ((kv._1, kv._2)) + b.result + } + + override def - (key: A): SortedMap[A, B] = { + val b = newBuilder + for (kv <- this; if kv._1 != key) b += kv + b.result + } + } } diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala index 4c1a5f2e03..51bc76efc3 100644 --- a/src/library/scala/collection/immutable/TreeMap.scala +++ b/src/library/scala/collection/immutable/TreeMap.scala @@ -131,7 +131,7 @@ class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Orderi * @param value the value to be associated with `key` * @return a new $coll with the updated binding */ - override def updated [B1 >: B](key: A, value: B1): TreeMap[A, B1] = new TreeMap(RB.update(tree, key, value)) + override def updated [B1 >: B](key: A, value: B1): TreeMap[A, B1] = new TreeMap(RB.update(tree, key, value, true)) /** Add a key/value pair to this map. * @tparam B1 type of the value of the new binding, a supertype of `B` @@ -171,7 +171,7 @@ class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Orderi */ def insert [B1 >: B](key: A, value: B1): TreeMap[A, B1] = { assert(!RB.contains(tree, key)) - new TreeMap(RB.update(tree, key, value)) + new TreeMap(RB.update(tree, key, value, true)) } def - (key:A): TreeMap[A, B] = diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala index 882e828c5b..697da2bc4b 100644 --- a/src/library/scala/collection/immutable/TreeSet.scala +++ b/src/library/scala/collection/immutable/TreeSet.scala @@ -112,7 +112,7 @@ class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Orderin * @param elem a new element to add. * @return a new $coll containing `elem` and all the elements of this $coll. */ - def + (elem: A): TreeSet[A] = newSet(RB.update(tree, elem, ())) + def + (elem: A): TreeSet[A] = newSet(RB.update(tree, elem, (), false)) /** A new `TreeSet` with the entry added is returned, * assuming that elem is <em>not</em> in the TreeSet. @@ -122,7 +122,7 @@ class TreeSet[A] private (tree: RB.Tree[A, Unit])(implicit val ordering: Orderin */ def insert(elem: A): TreeSet[A] = { assert(!RB.contains(tree, elem)) - newSet(RB.update(tree, elem, ())) + newSet(RB.update(tree, elem, (), false)) } /** Creates a new `TreeSet` with the entry removed. diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala index a7ec833193..82498f9b63 100644 --- a/src/library/scala/collection/parallel/ParIterableLike.scala +++ b/src/library/scala/collection/parallel/ParIterableLike.scala @@ -841,7 +841,7 @@ self: ParIterableLike[T, Repr, Sequential] => override def toBuffer[U >: T]: collection.mutable.Buffer[U] = seq.toBuffer // have additional, parallel buffers? - override def toTraversable: GenTraversable[T] = this.asInstanceOf[GenTraversable[T]] // TODO add ParTraversable[T] + override def toTraversable: GenTraversable[T] = this.asInstanceOf[GenTraversable[T]] override def toIterable: ParIterable[T] = this.asInstanceOf[ParIterable[T]] @@ -850,13 +850,13 @@ self: ParIterableLike[T, Repr, Sequential] => override def toSet[U >: T]: immutable.ParSet[U] = toParCollection[U, immutable.ParSet[U]](() => immutable.ParSet.newCombiner[U]) override def toMap[K, V](implicit ev: T <:< (K, V)): immutable.ParMap[K, V] = toParMap[K, V, immutable.ParMap[K, V]](() => immutable.ParMap.newCombiner[K, V]) - - // TODO(@alex22): make these better - override def toVector: Vector[T] = seq.toVector - - override def convertTo[Col[_]](implicit cbf: CanBuildFrom[Nothing, T, Col[T @uncheckedVariance]]): Col[T @uncheckedVariance] = seq.convertTo[Col] + override def toVector: Vector[T] = to[Vector] + override def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, T, Col[T @uncheckedVariance]]): Col[T @uncheckedVariance] = if (cbf().isCombiner) { + toParCollection[T, Col[T]](() => cbf().asCombiner) + } else seq.to(cbf) + /* tasks */ protected trait StrictSplitterCheckTask[R, Tp] extends Task[R, Tp] { diff --git a/src/library/scala/collection/parallel/immutable/ParIterable.scala b/src/library/scala/collection/parallel/immutable/ParIterable.scala index d8c42d74b0..349f4fa44c 100644 --- a/src/library/scala/collection/parallel/immutable/ParIterable.scala +++ b/src/library/scala/collection/parallel/immutable/ParIterable.scala @@ -34,6 +34,7 @@ extends collection/*.immutable*/.GenIterable[T] with collection.parallel.ParIterable[T] with GenericParTemplate[T, ParIterable] with ParIterableLike[T, ParIterable[T], collection.immutable.Iterable[T]] + with Immutable { override def companion: GenericCompanion[ParIterable] with GenericParCompanion[ParIterable] = ParIterable diff --git a/src/library/scala/collection/parallel/mutable/ParIterable.scala b/src/library/scala/collection/parallel/mutable/ParIterable.scala index 700d21d0bb..b5747a31cf 100644 --- a/src/library/scala/collection/parallel/mutable/ParIterable.scala +++ b/src/library/scala/collection/parallel/mutable/ParIterable.scala @@ -29,7 +29,8 @@ import scala.collection.GenIterable trait ParIterable[T] extends collection/*.mutable*/.GenIterable[T] with collection.parallel.ParIterable[T] with GenericParTemplate[T, ParIterable] - with ParIterableLike[T, ParIterable[T], Iterable[T]] { + with ParIterableLike[T, ParIterable[T], Iterable[T]] + with Mutable { override def companion: GenericCompanion[ParIterable] with GenericParCompanion[ParIterable] = ParIterable //protected[this] override def newBuilder = ParIterable.newBuilder[T] diff --git a/src/reflect/scala/reflect/internal/util/Statistics.scala b/src/reflect/scala/reflect/internal/util/Statistics.scala index f69530c40d..3a31c2858b 100644 --- a/src/reflect/scala/reflect/internal/util/Statistics.scala +++ b/src/reflect/scala/reflect/internal/util/Statistics.scala @@ -41,7 +41,7 @@ object Statistics { } /** If enabled, push and start a new timer in timer stack */ - @inline final def pushTimer(timers: TimerStack, timer: StackableTimer): TimerSnapshot = + @inline final def pushTimer(timers: TimerStack, timer: => StackableTimer): TimerSnapshot = if (_enabled && timers != null) timers.push(timer) else null /** If enabled, stop and pop timer from timer stack */ @@ -190,7 +190,7 @@ quant) * on access by executing `initValue`. */ class QuantMap[K, V <% Ordered[V]](val prefix: String, val phases: Seq[String], initValue: => V) - extends scala.collection.mutable.HashMap[K, V] with Quantity { + extends mutable.HashMap[K, V] with mutable.SynchronizedMap[K, V] with Quantity { override def default(key: K) = { val elem = initValue this(key) = elem diff --git a/test/files/continuations-neg/ts-1681-nontail-return.check b/test/files/continuations-neg/ts-1681-nontail-return.check deleted file mode 100644 index 8fe15f154b..0000000000 --- a/test/files/continuations-neg/ts-1681-nontail-return.check +++ /dev/null @@ -1,4 +0,0 @@ -ts-1681-nontail-return.scala:10: error: return expressions in CPS code must be in tail position - return v - ^ -one error found diff --git a/test/files/continuations-neg/ts-1681-nontail-return.scala b/test/files/continuations-neg/ts-1681-nontail-return.scala deleted file mode 100644 index af86ad304f..0000000000 --- a/test/files/continuations-neg/ts-1681-nontail-return.scala +++ /dev/null @@ -1,18 +0,0 @@ -import scala.util.continuations._ - -class ReturnRepro { - def s1: Int @cpsParam[Any, Unit] = shift { k => k(5) } - def caller = reset { println(p(3)) } - - def p(i: Int): Int @cpsParam[Unit, Any] = { - val v= s1 + 3 - if (v == 8) - return v - v + 1 - } -} - -object Test extends App { - val repro = new ReturnRepro - repro.caller -} diff --git a/test/files/continuations-run/ts-1681-2.check b/test/files/continuations-run/ts-1681-2.check deleted file mode 100644 index 35b3c93780..0000000000 --- a/test/files/continuations-run/ts-1681-2.check +++ /dev/null @@ -1,5 +0,0 @@ -8 -hi -8 -from try -8 diff --git a/test/files/continuations-run/ts-1681-2.scala b/test/files/continuations-run/ts-1681-2.scala deleted file mode 100644 index 8a896dec2c..0000000000 --- a/test/files/continuations-run/ts-1681-2.scala +++ /dev/null @@ -1,44 +0,0 @@ -import scala.util.continuations._ - -class ReturnRepro { - def s1: Int @cps[Any] = shift { k => k(5) } - def caller = reset { println(p(3)) } - def caller2 = reset { println(p2(3)) } - def caller3 = reset { println(p3(3)) } - - def p(i: Int): Int @cps[Any] = { - val v= s1 + 3 - return v - } - - def p2(i: Int): Int @cps[Any] = { - val v = s1 + 3 - if (v > 0) { - println("hi") - return v - } else { - println("hi") - return 8 - } - } - - def p3(i: Int): Int @cps[Any] = { - val v = s1 + 3 - try { - println("from try") - return v - } catch { - case e: Exception => - println("from catch") - return 7 - } - } - -} - -object Test extends App { - val repro = new ReturnRepro - repro.caller - repro.caller2 - repro.caller3 -} diff --git a/test/files/continuations-run/ts-1681-3.check b/test/files/continuations-run/ts-1681-3.check deleted file mode 100644 index 71489f097c..0000000000 --- a/test/files/continuations-run/ts-1681-3.check +++ /dev/null @@ -1,4 +0,0 @@ -enter return expr -8 -hi -8 diff --git a/test/files/continuations-run/ts-1681-3.scala b/test/files/continuations-run/ts-1681-3.scala deleted file mode 100644 index 62c547f5a2..0000000000 --- a/test/files/continuations-run/ts-1681-3.scala +++ /dev/null @@ -1,27 +0,0 @@ -import scala.util.continuations._ - -class ReturnRepro { - def s1: Int @cpsParam[Any, Unit] = shift { k => k(5) } - def caller = reset { println(p(3)) } - def caller2 = reset { println(p2(3)) } - - def p(i: Int): Int @cpsParam[Unit, Any] = { - val v= s1 + 3 - return { println("enter return expr"); v } - } - - def p2(i: Int): Int @cpsParam[Unit, Any] = { - val v = s1 + 3 - if (v > 0) { - return { println("hi"); v } - } else { - return { println("hi"); 8 } - } - } -} - -object Test extends App { - val repro = new ReturnRepro - repro.caller - repro.caller2 -} diff --git a/test/files/continuations-run/ts-1681.check b/test/files/continuations-run/ts-1681.check deleted file mode 100644 index 85176d8e66..0000000000 --- a/test/files/continuations-run/ts-1681.check +++ /dev/null @@ -1,3 +0,0 @@ -8 -hi -8 diff --git a/test/files/continuations-run/ts-1681.scala b/test/files/continuations-run/ts-1681.scala deleted file mode 100644 index efb1abae15..0000000000 --- a/test/files/continuations-run/ts-1681.scala +++ /dev/null @@ -1,29 +0,0 @@ -import scala.util.continuations._ - -class ReturnRepro { - def s1: Int @cpsParam[Any, Unit] = shift { k => k(5) } - def caller = reset { println(p(3)) } - def caller2 = reset { println(p2(3)) } - - def p(i: Int): Int @cpsParam[Unit, Any] = { - val v= s1 + 3 - return v - } - - def p2(i: Int): Int @cpsParam[Unit, Any] = { - val v = s1 + 3 - if (v > 0) { - println("hi") - return v - } else { - println("hi") - return 8 - } - } -} - -object Test extends App { - val repro = new ReturnRepro - repro.caller - repro.caller2 -} diff --git a/test/files/pos/t5846.scala b/test/files/pos/t5846.scala new file mode 100644 index 0000000000..b06f5ac39c --- /dev/null +++ b/test/files/pos/t5846.scala @@ -0,0 +1,10 @@ + + + + +/** Return the most general sorted map type. */ +object Test extends App { + + val empty: collection.SortedMap[String, String] = collection.SortedMap.empty[String, String] + +} diff --git a/test/files/pos/t5953.scala b/test/files/pos/t5953.scala index 90e7d84646..7ba035ec3b 100644 --- a/test/files/pos/t5953.scala +++ b/test/files/pos/t5953.scala @@ -10,7 +10,7 @@ package object foo { package foo { object Test { - def f1[T](xs: Traversable[T]) = xs.convertTo[immutable.Vector] + def f1[T](xs: Traversable[T]) = xs.to[immutable.Vector] def f2[T](xs: Traversable[T]) = xs.build[immutable.Vector] } } diff --git a/test/files/presentation/ide-bug-1000531.check b/test/files/presentation/ide-bug-1000531.check index 9d4674d7c7..4be98a6b21 100644 --- a/test/files/presentation/ide-bug-1000531.check +++ b/test/files/presentation/ide-bug-1000531.check @@ -25,7 +25,6 @@ retrieved 126 members [accessible: true] `method collectFirst[B](pf: PartialFunction[B,B])Option[B]` [accessible: true] `method collect[B](pf: PartialFunction[B,B])Iterator[B]` [accessible: true] `method contains(elem: Any)Boolean` -[accessible: true] `method convertTo[Col[_]](implicit cbf: scala.collection.generic.CanBuildFrom[Nothing,B,Col[B]])Col[B]` [accessible: true] `method copyToArray[B >: B](xs: Array[B])Unit` [accessible: true] `method copyToArray[B >: B](xs: Array[B], start: Int)Unit` [accessible: true] `method copyToArray[B >: B](xs: Array[B], start: Int, len: Int)Unit` @@ -111,6 +110,7 @@ retrieved 126 members [accessible: true] `method toString()String` [accessible: true] `method toTraversable=> Traversable[B]` [accessible: true] `method toVector=> Vector[B]` +[accessible: true] `method to[Col[_]](implicit cbf: scala.collection.generic.CanBuildFrom[Nothing,B,Col[B]])Col[B]` [accessible: true] `method wait()Unit` [accessible: true] `method wait(x$1: Long)Unit` [accessible: true] `method wait(x$1: Long, x$2: Int)Unit` diff --git a/test/files/run/collection-conversions.check b/test/files/run/collection-conversions.check index 08d0fa32c5..5e43d25f7e 100644 --- a/test/files/run/collection-conversions.check +++ b/test/files/run/collection-conversions.check @@ -11,6 +11,7 @@ :[Direct] Array : OK :[Copy] Array : OK :[Copy] ParVector: OK + :[Copy] ParArray : OK -- Testing Vector --- :[Direct] Vector : OK :[Copy] Vector : OK @@ -24,6 +25,7 @@ :[Direct] Array : OK :[Copy] Array : OK :[Copy] ParVector: OK + :[Copy] ParArray : OK -- Testing List --- :[Direct] Vector : OK :[Copy] Vector : OK @@ -37,6 +39,7 @@ :[Direct] Array : OK :[Copy] Array : OK :[Copy] ParVector: OK + :[Copy] ParArray : OK -- Testing Buffer --- :[Direct] Vector : OK :[Copy] Vector : OK @@ -50,6 +53,7 @@ :[Direct] Array : OK :[Copy] Array : OK :[Copy] ParVector: OK + :[Copy] ParArray : OK -- Testing ParVector --- :[Direct] Vector : OK :[Copy] Vector : OK @@ -63,6 +67,21 @@ :[Direct] Array : OK :[Copy] Array : OK :[Copy] ParVector: OK + :[Copy] ParArray : OK +-- Testing ParArray --- + :[Direct] Vector : OK + :[Copy] Vector : OK + :[Direct] Buffer : OK + :[Copy] Buffer : OK + :[Direct] GenSeq : OK + :[Copy] GenSeq : OK + :[Copy] Seq : OK + :[Direct] Stream : OK + :[Copy] Stream : OK + :[Direct] Array : OK + :[Copy] Array : OK + :[Copy] ParVector: OK + :[Copy] ParArray : OK -- Testing Set --- :[Direct] Vector : OK :[Copy] Vector : OK @@ -76,6 +95,7 @@ :[Direct] Array : OK :[Copy] Array : OK :[Copy] ParVector: OK + :[Copy] ParArray : OK -- Testing SetView --- :[Direct] Vector : OK :[Copy] Vector : OK @@ -89,6 +109,7 @@ :[Direct] Array : OK :[Copy] Array : OK :[Copy] ParVector: OK + :[Copy] ParArray : OK -- Testing BufferView --- :[Direct] Vector : OK :[Copy] Vector : OK @@ -102,3 +123,4 @@ :[Direct] Array : OK :[Copy] Array : OK :[Copy] ParVector: OK + :[Copy] ParArray : OK
\ No newline at end of file diff --git a/test/files/run/collection-conversions.scala b/test/files/run/collection-conversions.scala index b5c4d8e261..d842742230 100644 --- a/test/files/run/collection-conversions.scala +++ b/test/files/run/collection-conversions.scala @@ -1,6 +1,7 @@ import collection._ import mutable.Buffer import parallel.immutable.ParVector +import parallel.mutable.ParArray import reflect.ClassTag object Test { @@ -29,30 +30,33 @@ object Test { val testStream = Stream(1,2,3) val testArray = Array(1,2,3) val testParVector = ParVector(1,2,3) + val testParArray = ParArray(1,2,3) def testConversion[A: ClassTag](name: String, col: => GenTraversableOnce[A]): Unit = { val tmp = col println("-- Testing " + name + " ---") printResult("[Direct] Vector ", col.toVector, testVector) - printResult("[Copy] Vector ", col.convertTo[Vector], testVector) + printResult("[Copy] Vector ", col.to[Vector], testVector) printResult("[Direct] Buffer ", col.toBuffer, testBuffer) - printResult("[Copy] Buffer ", col.convertTo[Buffer], testBuffer) + printResult("[Copy] Buffer ", col.to[Buffer], testBuffer) printResult("[Direct] GenSeq ", col.toSeq, testGenSeq) - printResult("[Copy] GenSeq ", col.convertTo[GenSeq], testGenSeq) - printResult("[Copy] Seq ", col.convertTo[Seq], testSeq) + printResult("[Copy] GenSeq ", col.to[GenSeq], testGenSeq) + printResult("[Copy] Seq ", col.to[Seq], testSeq) printResult("[Direct] Stream ", col.toStream, testStream) - printResult("[Copy] Stream ", col.convertTo[Stream], testStream) + printResult("[Copy] Stream ", col.to[Stream], testStream) printResult("[Direct] Array ", col.toArray, testArray) - printResult("[Copy] Array ", col.convertTo[Array], testArray) - printResult("[Copy] ParVector", col.convertTo[ParVector], testParVector) + printResult("[Copy] Array ", col.to[Array], testArray) + printResult("[Copy] ParVector", col.to[ParVector], testParVector) + printResult("[Copy] ParArray ", col.to[ParArray], testParArray) } def main(args: Array[String]): Unit = { - testConversion("iterator", (1 to 3).iterator) + testConversion("iterator", (1 to 3).iterator) testConversion("Vector", Vector(1,2,3)) testConversion("List", List(1,2,3)) testConversion("Buffer", Buffer(1,2,3)) testConversion("ParVector", ParVector(1,2,3)) + testConversion("ParArray", ParArray(1,2,3)) testConversion("Set", Set(1,2,3)) testConversion("SetView", Set(1,2,3).view) testConversion("BufferView", Buffer(1,2,3).view) diff --git a/test/files/run/t3326.check b/test/files/run/t3326.check new file mode 100644 index 0000000000..d0e11cebf7 --- /dev/null +++ b/test/files/run/t3326.check @@ -0,0 +1,8 @@ +Map(2 -> Hello, 1 -> World) +Map(5 -> Foo, 4 -> Bar) +Map(5 -> Foo, 4 -> Bar, 2 -> Hello, 1 -> World) +Map(3 -> ?, 2 -> Hello, 1 -> World) +Map(2 -> Hello, 1 -> World) +Map(5 -> Foo, 4 -> Bar) +Map(5 -> Foo, 4 -> Bar, 2 -> Hello, 1 -> World) +Map(3 -> ?, 2 -> Hello, 1 -> World)
\ No newline at end of file diff --git a/test/files/run/t3326.scala b/test/files/run/t3326.scala new file mode 100644 index 0000000000..f70cb01504 --- /dev/null +++ b/test/files/run/t3326.scala @@ -0,0 +1,74 @@ + + + +import scala.math.Ordering + + + +/** The heart of the problem - we want to retain the ordering when + * using `++` on sorted maps. + * + * There are 2 `++` overloads - a generic one in traversables and + * a map-specific one in `MapLike` - which knows about the ordering. + * + * The problem here is that the expected return type for the expression + * in which `++` appears drives the decision of the overload that needs + * to be taken. + * The `collection.SortedMap` does not have `++` overridden to return + * `SortedMap`, but `immutable.Map` instead. + * This is why `collection.SortedMap` used to resort to the generic + * `TraversableLike.++` which knows nothing about the ordering. + * + * To avoid `collection.SortedMap`s resort to the more generic `TraverableLike.++`, + * we override the `MapLike.++` overload in `collection.SortedMap` to return + * the proper type `SortedMap`. + */ +object Test { + + def main(args: Array[String]) { + testCollectionSorted() + testImmutableSorted() + } + + def testCollectionSorted() { + import collection._ + val order = implicitly[Ordering[Int]].reverse + var m1: SortedMap[Int, String] = SortedMap.empty[Int, String](order) + var m2: SortedMap[Int, String] = SortedMap.empty[Int, String](order) + + m1 += (1 -> "World") + m1 += (2 -> "Hello") + + m2 += (4 -> "Bar") + m2 += (5 -> "Foo") + + val m3: SortedMap[Int, String] = m1 ++ m2 + + println(m1) + println(m2) + println(m3) + + println(m1 + (3 -> "?")) + } + + def testImmutableSorted() { + import collection.immutable._ + val order = implicitly[Ordering[Int]].reverse + var m1: SortedMap[Int, String] = SortedMap.empty[Int, String](order) + var m2: SortedMap[Int, String] = SortedMap.empty[Int, String](order) + + m1 += (1 -> "World") + m1 += (2 -> "Hello") + + m2 += (4 -> "Bar") + m2 += (5 -> "Foo") + + val m3: SortedMap[Int, String] = m1 ++ m2 + + println(m1) + println(m2) + println(m3) + + println(m1 + (3 -> "?")) + } +} diff --git a/test/files/run/t4027.check b/test/files/run/t4027.check new file mode 100644 index 0000000000..bdacfc1c06 --- /dev/null +++ b/test/files/run/t4027.check @@ -0,0 +1,12 @@ +Map(2 -> true, 4 -> true) +Map(1 -> false!, 2 -> true!, 3 -> false!, 4 -> true!) +Map(2 -> 4, 4 -> 4) +Map(1 -> 6, 2 -> 5, 3 -> 6, 4 -> 5) +Map() +Map(1 -> false!) +Map(2 -> true, 4 -> true) +Map(1 -> false!, 2 -> true!, 3 -> false!, 4 -> true!) +Map(2 -> 4, 4 -> 4) +Map(1 -> 6, 2 -> 5, 3 -> 6, 4 -> 5) +Map() +Map(1 -> false!)
\ No newline at end of file diff --git a/test/files/run/t4027.scala b/test/files/run/t4027.scala new file mode 100644 index 0000000000..d70ca0cc3a --- /dev/null +++ b/test/files/run/t4027.scala @@ -0,0 +1,27 @@ + + +import collection._ + + +/** Sorted maps should have `filterKeys` and `mapValues` which return sorted maps. + * Mapping, filtering, etc. on these views should return sorted maps again. + */ +object Test extends App { + + val sortedmap = SortedMap(1 -> false, 2 -> true, 3 -> false, 4 -> true) + println(sortedmap.filterKeys(_ % 2 == 0): SortedMap[Int, Boolean]) + println(sortedmap.mapValues(_ + "!"): SortedMap[Int, String]) + println(sortedmap.filterKeys(_ % 2 == 0).map(t => (t._1, t._2.toString.length)): SortedMap[Int, Int]) + println(sortedmap.mapValues(_ + "!").map(t => (t._1, t._2.toString.length)): SortedMap[Int, Int]) + println(sortedmap.filterKeys(_ % 2 == 0).filter(t => t._1 < 2): SortedMap[Int, Boolean]) + println(sortedmap.mapValues(_ + "!").filter(t => t._1 < 2): SortedMap[Int, String]) + + val immsortedmap = immutable.SortedMap(1 -> false, 2 -> true, 3 -> false, 4 -> true) + println(immsortedmap.filterKeys(_ % 2 == 0): immutable.SortedMap[Int, Boolean]) + println(immsortedmap.mapValues(_ + "!"): immutable.SortedMap[Int, String]) + println(immsortedmap.filterKeys(_ % 2 == 0).map(t => (t._1, t._2.toString.length)): immutable.SortedMap[Int, Int]) + println(immsortedmap.mapValues(_ + "!").map(t => (t._1, t._2.toString.length)): immutable.SortedMap[Int, Int]) + println(immsortedmap.filterKeys(_ % 2 == 0).filter(t => t._1 < 2): immutable.SortedMap[Int, Boolean]) + println(immsortedmap.mapValues(_ + "!").filter(t => t._1 < 2): immutable.SortedMap[Int, String]) + +} diff --git a/test/files/run/t5986.check b/test/files/run/t5986.check new file mode 100644 index 0000000000..4101770c6d --- /dev/null +++ b/test/files/run/t5986.check @@ -0,0 +1,15 @@ +Foo(bar, 1) +Foo(bar, 1) +Foo(bar, 1),Foo(baz, 3),Foo(bazz, 4) +Foo(bar, 1) +Foo(bar, 1) +Foo(bar, 1),Foo(baz, 3),Foo(bazz, 4) +Foo(bar, 1) +Foo(bar, 1) +Foo(bar, 1),Foo(baz, 3),Foo(bazz, 4) +Foo(bar, 1) +Foo(bar, 1) +Foo(bar, 1),Foo(baz, 3),Foo(bazz, 4) +Foo(bar, 1) +Foo(bar, 1) +Foo(bar, 1),Foo(baz, 3),Foo(bazz, 4)
\ No newline at end of file diff --git a/test/files/run/t5986.scala b/test/files/run/t5986.scala new file mode 100644 index 0000000000..8cf7086f98 --- /dev/null +++ b/test/files/run/t5986.scala @@ -0,0 +1,36 @@ + + + +import scala.collection._ + + + +/** A sorted set should not replace elements when adding + * and the element already exists in the set. + */ +object Test { + + class Foo(val name: String, val n: Int) { + override def equals(obj: Any): Boolean = obj match { case other: Foo => name == other.name; case _ => false } + override def hashCode = name.## + override def toString = "Foo(" + name + ", " + n + ")" + } + + implicit val ordering: Ordering[Foo] = Ordering.fromLessThan[Foo] { (a, b) => a.name.compareTo(b.name) < 0 } + + def check[S <: Set[Foo]](set: S) { + def output(s: Set[Foo]) = println(s.toList.sorted.mkString(",")) + output(set + new Foo("bar", 2)) + output(set ++ List(new Foo("bar", 2), new Foo("bar", 3), new Foo("bar", 4))) + output(set union Set(new Foo("bar", 2), new Foo("baz", 3), new Foo("bazz", 4))) + } + + def main(args: Array[String]) { + check(Set(new Foo("bar", 1))) + check(immutable.Set(new Foo("bar", 1))) + check(mutable.Set(new Foo("bar", 1))) + check(immutable.SortedSet(new Foo("bar", 1))) + check(mutable.SortedSet(new Foo("bar", 1))) + } + +} diff --git a/test/files/scalacheck/redblacktree.scala b/test/files/scalacheck/redblacktree.scala index e4b356c889..e2609fa200 100644 --- a/test/files/scalacheck/redblacktree.scala +++ b/test/files/scalacheck/redblacktree.scala @@ -121,7 +121,7 @@ package scala.collection.immutable.redblacktree { override type ModifyParm = Int override def genParm(tree: Tree[String, Int]): Gen[ModifyParm] = choose(0, iterator(tree).size + 1) - override def modify(tree: Tree[String, Int], parm: ModifyParm): Tree[String, Int] = update(tree, generateKey(tree, parm), 0) + override def modify(tree: Tree[String, Int], parm: ModifyParm): Tree[String, Int] = update(tree, generateKey(tree, parm), 0, true) def generateKey(tree: Tree[String, Int], parm: ModifyParm): String = nodeAt(tree, parm) match { case Some((key, _)) => key.init.mkString + "MN" @@ -144,7 +144,7 @@ package scala.collection.immutable.redblacktree { override type ModifyParm = Int override def genParm(tree: Tree[String, Int]): Gen[ModifyParm] = choose(0, iterator(tree).size) override def modify(tree: Tree[String, Int], parm: ModifyParm): Tree[String, Int] = nodeAt(tree, parm) map { - case (key, _) => update(tree, key, newValue) + case (key, _) => update(tree, key, newValue, true) } getOrElse tree property("update modifies values") = forAll(genInput) { case (tree, parm, newTree) => |