Skip to content

Commit

Permalink
fixup! [bug#3088][bug#12121] Fix adding/subtracting ListBuffer to/fro…
Browse files Browse the repository at this point in the history
…m itself

quadruple the size of ListBuffer#insertAll
  • Loading branch information
NthPortal committed Oct 2, 2020
1 parent 433afe7 commit 762676c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
30 changes: 24 additions & 6 deletions src/library/scala/collection/mutable/ListBuffer.scala
Expand Up @@ -127,6 +127,7 @@ class ListBuffer[A]
val copy = ListBuffer.from(this)
last0.next = copy.first
last0 = copy.last0
len *= 2
}
case xs =>
val it = xs.iterator
Expand Down Expand Up @@ -246,12 +247,29 @@ class ListBuffer[A]
}

def insertAll(idx: Int, elems: IterableOnce[A]): Unit = {
val it = elems.iterator
if (it.hasNext) {
ensureUnaliased()
if (idx < 0 || idx > len) throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${len-1})")
if (idx == len) ++=(elems)
else insertAfter(locate(idx), it)
if (idx < 0 || idx > len) throw new IndexOutOfBoundsException(s"$idx is out of bounds (min 0, max ${len-1})")
elems match {
case elems: AnyRef if elems eq this => // avoid mutating under our own iterator
if (len > 0) {
val copy = ListBuffer.from(this)
if (idx == 0 || idx == len) { // prepend/append
last0.next = copy.first
last0 = copy.last0
} else {
val prev = locate(idx) // cannot be `null` because other condition catches that
val follow = prev.next
prev.next = copy.first
copy.last0.next = follow
}
len *= 2
}
case elems =>
val it = elems.iterator
if (it.hasNext) {
ensureUnaliased()
if (idx == len) ++=(elems)
else insertAfter(locate(idx), it)
}
}
}

Expand Down
36 changes: 36 additions & 0 deletions test/junit/scala/collection/mutable/ListBufferTest.scala
Expand Up @@ -3,6 +3,8 @@ package scala.collection.mutable
import org.junit.Assert.{assertEquals, assertTrue}
import org.junit.Test

import scala.tools.testkit.AssertUtil.assertSameElements

import scala.annotation.nowarn

class ListBufferTest {
Expand Down Expand Up @@ -228,4 +230,38 @@ class ListBufferTest {
b += "b"
assertEquals(Seq("a1", "b"), b)
}

/* tests for scala/bug#12121 */

@Test
def self_addAll(): Unit = {
val b = ListBuffer(1, 2, 3)
b ++= b
assertSameElements(List(1, 2, 3, 1, 2, 3), b)
}

@Test
def self_prependAll(): Unit = {
val b = ListBuffer(1, 2, 3)
b prependAll b
assertSameElements(List(1, 2, 3, 1, 2, 3), b)
}

@Test
def self_insertAll(): Unit = {
val b1 = ListBuffer(1, 2, 3)
b1.insertAll(1, b1)
assertSameElements(List(1, 1, 2, 3, 2, 3), b1)

val b2 = ListBuffer(1, 2, 3)
b2.insertAll(3, b2)
assertSameElements(List(1, 2, 3, 1, 2, 3), b2)
}

@Test
def self_subtractAll(): Unit = {
val b = ListBuffer(1, 2, 3)
b --= b
assertSameElements(Nil, b)
}
}

0 comments on commit 762676c

Please sign in to comment.