aboutsummaryrefslogtreecommitdiff
path: root/tests/pos/tailcall/i321.scala
blob: daa078dd5093baf76beb78a568f6783e7a65fe3d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import scala.annotation.tailrec
/**
 * Illustrates that abstracting over type arguments without triggering Ycheck failure is tricky
 *
 * go1.loop refers to type parameter of i321, and captures value f
 * if go1.loop will abstract over T it will need to cast f or will trigger a Ycheck failure.
 * One could decide to not abstract over type parameters in tail calls, but this leads us to go2 example
 *
 * In go2 we should abstract over i321.T, as we need to change it in recursive call.
 *
 * For now decision is such - we will abstract for top-level methods, but will not for inner ones.
 */

class i321[T >: Null <: AnyRef] {

  def go1(f: T => Int): Int = {
    @tailrec def loop(pending: T): Int = {
      val head1 = f(pending)
      loop(pending)
    }
    loop(null)
  }

  final def go2[U >: Null <: AnyRef](t: i321[U]): Int = t.go2(this)

}