aboutsummaryrefslogtreecommitdiff
path: root/tests/pos/tailcall
diff options
context:
space:
mode:
authorDmitry Petrashko <dmitry.petrashko@gmail.com>2015-01-26 14:20:18 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2015-02-03 15:10:10 +0100
commit12d4182cc9da27eca9d55a94d148f4a8dadbc11d (patch)
tree9d74e6ed566be48bd89916756b00f8a1b6284758 /tests/pos/tailcall
parenta14af3e7bf82e793d0b687bf6e53b6bc61f1ec5a (diff)
downloaddotty-12d4182cc9da27eca9d55a94d148f4a8dadbc11d.tar.gz
dotty-12d4182cc9da27eca9d55a94d148f4a8dadbc11d.tar.bz2
dotty-12d4182cc9da27eca9d55a94d148f4a8dadbc11d.zip
Even more careful handling of tailcalls.
See i321 doc for description of problem and decision taken.
Diffstat (limited to 'tests/pos/tailcall')
-rw-r--r--tests/pos/tailcall/i321.scala26
1 files changed, 21 insertions, 5 deletions
diff --git a/tests/pos/tailcall/i321.scala b/tests/pos/tailcall/i321.scala
index 0d32dd625..33b3075de 100644
--- a/tests/pos/tailcall/i321.scala
+++ b/tests/pos/tailcall/i321.scala
@@ -1,10 +1,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 goo1.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 mapconserve(f: T => Int): Int = {
- def loop(pending: T): Int = {
- val head1 = f(pending)
- loop(pending)
- }
+ 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)
+
} \ No newline at end of file