Skip to content

Commit c79ff64

Browse files
authored
Merge pull request scala/scala#10640 from lrytz/t12921-backport
[backport] Fix RedBlackTree.doFrom / doTo / doUntil
2 parents 491a329 + 848337d commit c79ff64

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

library/src/scala/collection/immutable/RedBlackTree.scala

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,21 @@ import scala.annotation.tailrec
2525
* optimizations behind a reasonably clean API.
2626
*/
2727
private[collection] object NewRedBlackTree {
28+
def validate[A](tree: Tree[A, _])(implicit ordering: Ordering[A]): tree.type = {
29+
def impl(tree: Tree[A, _], keyProp: A => Boolean): Int = {
30+
assert(keyProp(tree.key), s"key check failed: $tree")
31+
if (tree.isRed) {
32+
assert(tree.left == null || tree.left.isBlack, s"red-red left $tree")
33+
assert(tree.right == null || tree.right.isBlack, s"red-red right $tree")
34+
}
35+
val leftBlacks = if (tree.left == null) 0 else impl(tree.left, k => keyProp(k) && ordering.compare(k, tree.key) < 0)
36+
val rightBlacks = if (tree.right == null) 0 else impl(tree.right, k => keyProp(k) && ordering.compare(k, tree.key) > 0)
37+
assert(leftBlacks == rightBlacks, s"not balanced: $tree")
38+
leftBlacks + (if (tree.isBlack) 1 else 0)
39+
}
40+
if (tree != null) impl(tree, _ => true)
41+
tree
42+
}
2843

2944
def isEmpty(tree: Tree[_, _]): Boolean = tree eq null
3045

@@ -447,23 +462,23 @@ private[collection] object NewRedBlackTree {
447462
if (ordering.lt(tree.key, from)) return doFrom(tree.right, from)
448463
val newLeft = doFrom(tree.left, from)
449464
if (newLeft eq tree.left) tree
450-
else if (newLeft eq null) upd(tree.right, tree.key, tree.value, overwrite = false)
465+
else if (newLeft eq null) maybeBlacken(upd(tree.right, tree.key, tree.value, overwrite = false))
451466
else join(newLeft, tree.key, tree.value, tree.right)
452467
}
453468
private[this] def doTo[A, B](tree: Tree[A, B], to: A)(implicit ordering: Ordering[A]): Tree[A, B] = {
454469
if (tree eq null) return null
455470
if (ordering.lt(to, tree.key)) return doTo(tree.left, to)
456471
val newRight = doTo(tree.right, to)
457472
if (newRight eq tree.right) tree
458-
else if (newRight eq null) upd(tree.left, tree.key, tree.value, overwrite = false)
459-
else join (tree.left, tree.key, tree.value, newRight)
473+
else if (newRight eq null) maybeBlacken(upd(tree.left, tree.key, tree.value, overwrite = false))
474+
else join(tree.left, tree.key, tree.value, newRight)
460475
}
461476
private[this] def doUntil[A, B](tree: Tree[A, B], until: A)(implicit ordering: Ordering[A]): Tree[A, B] = {
462477
if (tree eq null) return null
463478
if (ordering.lteq(until, tree.key)) return doUntil(tree.left, until)
464479
val newRight = doUntil(tree.right, until)
465480
if (newRight eq tree.right) tree
466-
else if (newRight eq null) upd(tree.left, tree.key, tree.value, overwrite = false)
481+
else if (newRight eq null) maybeBlacken(upd(tree.left, tree.key, tree.value, overwrite = false))
467482
else join(tree.left, tree.key, tree.value, newRight)
468483
}
469484

0 commit comments

Comments
 (0)