summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library/scala/collection/mutable/MapLike.scala4
-rw-r--r--src/library/scala/collection/mutable/SetLike.scala4
-rw-r--r--test/files/run/t7269.scala32
3 files changed, 37 insertions, 3 deletions
diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala
index a53aa3b76a..42e5a0a4c4 100644
--- a/src/library/scala/collection/mutable/MapLike.scala
+++ b/src/library/scala/collection/mutable/MapLike.scala
@@ -209,8 +209,8 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
* @param p The test predicate
*/
def retain(p: (A, B) => Boolean): this.type = {
- for ((k, v) <- this.seq ; if !p(k, v))
- this -= k
+ for ((k, v) <- this.toList) // SI-7269 toList avoids ConcurrentModificationException
+ if (!p(k, v)) this -= k
this
}
diff --git a/src/library/scala/collection/mutable/SetLike.scala b/src/library/scala/collection/mutable/SetLike.scala
index 01f87447ae..71da4c89dc 100644
--- a/src/library/scala/collection/mutable/SetLike.scala
+++ b/src/library/scala/collection/mutable/SetLike.scala
@@ -120,7 +120,9 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
* which `p` returns `true` are retained in the set; all others
* are removed.
*/
- def retain(p: A => Boolean): Unit = for (elem <- this.toList) if (!p(elem)) this -= elem
+ def retain(p: A => Boolean): Unit =
+ for (elem <- this.toList) // SI-7269 toList avoids ConcurrentModificationException
+ if (!p(elem)) this -= elem
/** Removes all elements from the set. After this operation is completed,
* the set will be empty.
diff --git a/test/files/run/t7269.scala b/test/files/run/t7269.scala
new file mode 100644
index 0000000000..d22e57dfee
--- /dev/null
+++ b/test/files/run/t7269.scala
@@ -0,0 +1,32 @@
+import scala.collection.JavaConversions._
+import scala.collection.mutable
+
+object Test extends App {
+
+ def testMap(): Unit = {
+ val mapJ = new java.util.HashMap[Int, String]
+ val mapS: mutable.Map[Int, String] = mapJ
+
+ (10 to 20).foreach(i => mapS += ((i, i.toString)))
+ assert(11 == mapS.size)
+
+ // ConcurrentModificationException thrown in the following line
+ mapS.retain((i, str) => i % 2 == 0)
+ assert(6 == mapS.size)
+ }
+
+ def testSet(): Unit = {
+ val mapJ = new java.util.HashSet[Int]
+ val mapS: mutable.Set[Int] = mapJ
+
+ (10 to 20).foreach(i => mapS += i)
+ assert(11 == mapS.size)
+
+ // ConcurrentModificationException thrown in the following line
+ mapS.retain((i) => i % 2 == 0)
+ assert(6 == mapS.size)
+ }
+
+ testSet()
+ testMap()
+}