From e0079c4274e418720c54b5e06e08adef023d7e79 Mon Sep 17 00:00:00 2001 From: Pavel Pavlov Date: Sat, 8 Feb 2014 19:34:26 +0700 Subject: SI-8251 deprecate `ListBuffer::readOnly` This is the first step towards fixing the unexpected behavior of `ListBuffer`. Many of `ListBuffer`'s operations are forwarded to the underlying `List`, essentially leaking that abstraction to clients that call e.g., `toIterable`. When the buffer changes, the `Iterable` obtained through `toIterable` will reflect that change. To avoid this exposure, call `toList` to obtain an immutable copy. See also: https://groups.google.com/d/msg/scala-internals/g_-gIWgB8Os/kWazrALbLKEJ https://gist.github.com/paulp/9081797 --- src/library/scala/collection/mutable/BufferLike.scala | 6 ++++-- src/library/scala/collection/mutable/ListBuffer.scala | 5 +++-- src/library/scala/collection/mutable/Map.scala | 12 ------------ test/files/run/t4288.scala | 2 +- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/library/scala/collection/mutable/BufferLike.scala b/src/library/scala/collection/mutable/BufferLike.scala index 7ba0b27ce5..3c57387c03 100644 --- a/src/library/scala/collection/mutable/BufferLike.scala +++ b/src/library/scala/collection/mutable/BufferLike.scala @@ -211,9 +211,11 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]] */ override def stringPrefix: String = "Buffer" - /** Provide a read-only view of this buffer as a sequence - * @return A sequence which refers to this buffer for all its operations. + /** Returns the current evolving(!) state of this buffer as a read-only sequence. + * + * @return A sequence that forwards to this buffer for all its operations. */ + @deprecated("The returned sequence changes as this buffer is mutated. For an immutable copy, use, e.g., toList.", "2.11.0") def readOnly: scala.collection.Seq[A] = toSeq /** Creates a new collection containing both the elements of this collection and the provided diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index e76825cea9..5e838d0d88 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -13,6 +13,7 @@ package mutable import generic._ import immutable.{List, Nil, ::} import java.io._ +import scala.annotation.migration /** A `Buffer` implementation back up by a list. It provides constant time * prepend and append. Most other operations are linear. @@ -262,7 +263,7 @@ final class ListBuffer[A] * @param n the index which refers to the first element to remove. * @param count the number of elements to remove. */ - @scala.annotation.migration("Invalid input values will be rejected in future releases.", "2.11") + @migration("Invalid input values will be rejected in future releases.", "2.11") override def remove(n: Int, count: Int) { if (n >= len) return @@ -407,7 +408,7 @@ final class ListBuffer[A] } } - /** expose the underlying list but do not mark it as exported */ + @deprecated("The result of this method will change along with this buffer, which is often not what's expected.", "2.11.0") override def readOnly: List[A] = start // Private methods diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index fe29ce4221..2ac3cb65b5 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -47,18 +47,6 @@ trait Map[A, B] * @return a wrapper of the map with a default value */ def withDefaultValue(d: B): mutable.Map[A, B] = new Map.WithDefault[A, B](this, x => d) - - /* Return a read-only projection of this map. !!! or just use an (immutable) MapProxy? - def readOnly : scala.collection.Map[A, B] = new scala.collection.Map[A, B] { - override def size = self.size - override def update(key: A, value: B) = self.update(key, value) - override def - (elem: A) = self - elem - override def iterator = self.iterator - override def foreach[U](f: ((A, B)) => U) = self.foreach(f) - override def empty[C] = self.empty[C] - def get(key: A) = self.get(key) - } - */ } /** $factoryInfo diff --git a/test/files/run/t4288.scala b/test/files/run/t4288.scala index 4e7b366f60..23319d1c27 100644 --- a/test/files/run/t4288.scala +++ b/test/files/run/t4288.scala @@ -1,6 +1,6 @@ object Test { def f1 = scala.collection.mutable.ListBuffer(1 to 9: _*).slice(-5, -1) - def f2 = scala.collection.mutable.ListBuffer(1 to 9: _*).readOnly.slice(-5, -1) + def f2 = List(1 to 9: _*).slice(-5, -1) def f3 = Vector(1 to 9: _*).slice(-5, -1) def f4 = Traversable(1 to 9: _*).slice(-5, -1) def f5 = (1 to 9).toArray.slice(-5, -1) -- cgit v1.2.3