Skip to content

Commit 50b53dc

Browse files
committed
fix #7034: make mapWithIndexConserve tailrec
1 parent 10145ff commit 50b53dc

File tree

2 files changed

+4803
-11
lines changed

2 files changed

+4803
-11
lines changed

compiler/src/dotty/tools/dotc/core/Decorators.scala

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,29 @@ object Decorators {
162162
* `xs` to themselves.
163163
*/
164164
def mapWithIndexConserve[U <: T](f: (T, Int) => U): List[U] =
165-
def recur(xs: List[T], idx: Int): List[U] =
166-
if xs.isEmpty then Nil
167-
else
168-
val x1 = f(xs.head, idx)
169-
val xs1 = recur(xs.tail, idx + 1)
170-
if (x1.asInstanceOf[AnyRef] eq xs.head.asInstanceOf[AnyRef])
171-
&& (xs1 eq xs.tail)
172-
then xs.asInstanceOf[List[U]]
173-
else x1 :: xs1
174-
recur(xs, 0)
165+
166+
@tailrec
167+
def addAll(buf: ListBuffer[T], from: List[T], until: List[T]): ListBuffer[T] =
168+
if from eq until then buf else addAll(buf += from.head, from.tail, until)
169+
170+
@tailrec
171+
def loopWithBuffer(buf: ListBuffer[U], explore: List[T], idx: Int): List[U] = explore match
172+
case Nil => buf.toList
173+
case t :: rest => loopWithBuffer(buf += f(t, idx), rest, idx + 1)
174+
175+
@tailrec
176+
def loop(keep: List[T], explore: List[T], idx: Int, keepCount: Int): List[U] = explore match
177+
case Nil => keep.asInstanceOf[List[U]]
178+
case t :: rest =>
179+
val u = f(t, idx)
180+
if u.asInstanceOf[AnyRef] eq t.asInstanceOf[AnyRef] then
181+
loop(keep, rest, idx + 1, keepCount + 1)
182+
else
183+
val buf = addAll(new ListBuffer[T], keep, explore).asInstanceOf[ListBuffer[U]]
184+
loopWithBuffer(buf += u, rest, idx + 1)
185+
186+
loop(xs, xs, 0, 0)
187+
end mapWithIndexConserve
175188

176189
final def hasSameLengthAs[U](ys: List[U]): Boolean = {
177190
@tailrec def loop(xs: List[T], ys: List[U]): Boolean =
@@ -278,4 +291,3 @@ object Decorators {
278291
def binarySearch(x: T): Int = java.util.Arrays.binarySearch(arr.asInstanceOf[Array[Object]], x)
279292

280293
}
281-

0 commit comments

Comments
 (0)