From be7a9a205c30b66b0b0fc37079e7ab75c5f14d2e Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 6 Sep 2017 07:59:12 +0200 Subject: [PATCH 1/2] Mitigate #2924 To make the stack shorter we implement foldRightBN with a foldLeftBN which allocates only half of the closures. By doing so we need to eagerly reverse the list which is in most cases small or empty. --- compiler/src/dotty/tools/dotc/core/Decorators.scala | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index 2bdb6f171cb3..fb93d922a8f3 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -112,9 +112,15 @@ object Decorators { else x1 :: xs1 } - def foldRightBN[U](z: => U)(op: (T, => U) => U): U = xs match { - case Nil => z - case x :: xs1 => op(x, xs1.foldRightBN(z)(op)) + def foldRightBN[U](z: => U)(op: (T, => U) => U): U = + xs.reverse.foldLeftBN(z)(op) + + final def foldLeftBN[U](acc: => U)(op: (T, => U) => U): U = { + @tailrec def fold(xs: List[T], acc: => U): U = xs match { + case x :: xs1 => fold(xs1, op(x, acc)) + case Nil => acc + } + fold(xs, acc) } final def hasSameLengthAs[U](ys: List[U]): Boolean = { From 00e139ca4a723a0391fdda0bd7e28d15b17a5712 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 6 Sep 2017 10:11:28 +0200 Subject: [PATCH 2/2] Make inline foldLeftBN into foldRightBN to avoid reversed params --- compiler/src/dotty/tools/dotc/core/Decorators.scala | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index fb93d922a8f3..eb69f9ef637d 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -112,15 +112,12 @@ object Decorators { else x1 :: xs1 } - def foldRightBN[U](z: => U)(op: (T, => U) => U): U = - xs.reverse.foldLeftBN(z)(op) - - final def foldLeftBN[U](acc: => U)(op: (T, => U) => U): U = { - @tailrec def fold(xs: List[T], acc: => U): U = xs match { - case x :: xs1 => fold(xs1, op(x, acc)) + def foldRightBN[U](z: => U)(op: (T, => U) => U): U = { + @tailrec def foldLeftBN(xs: List[T], acc: => U): U = xs match { + case x :: xs1 => foldLeftBN(xs1, op(x, acc)) case Nil => acc } - fold(xs, acc) + foldLeftBN(xs.reverse, z) } final def hasSameLengthAs[U](ys: List[U]): Boolean = {