Skip to content

Commit d96a500

Browse files
authored
Merge pull request #12972 from dotty-staging/fix-7034
fix #7034: make mapWithIndexConserve tailrec
2 parents ee97bdb + 81c96d7 commit d96a500

File tree

4 files changed

+4810
-12
lines changed

4 files changed

+4810
-12
lines changed

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

+23-11
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): 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)
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)
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-

compiler/test/dotc/pos-from-tasty.blacklist

+3
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ i10511.scala
1414

1515
# Violates tightened condition in Retyper#typedTyped
1616
i11247.scala
17+
18+
# Tree is huge and blows stack for printing Text
19+
i7034.scala

compiler/test/dotc/pos-test-pickling.blacklist

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ i7740b.scala
1818
i6507b.scala
1919
i12299a.scala
2020

21+
# Tree is huge and blows stack for printing Text
22+
i7034.scala
23+
2124
# Stale symbol: package object scala
2225
seqtype-cycle
2326

@@ -66,4 +69,4 @@ i2797a
6669
# GADT cast applied to singleton type difference
6770
i4176-gadt.scala
6871

69-
java-inherited-type1
72+
java-inherited-type1

0 commit comments

Comments
 (0)