diff options
author | Paul Phillips <paulp@improving.org> | 2010-04-15 22:18:15 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-04-15 22:18:15 +0000 |
commit | 11398dd393fe3eff544bfbafafb584d3acd66e05 (patch) | |
tree | bdbcc39f71339813abb55689eeb99ef9c417d2c7 /test | |
parent | 41860ffcf7b29f8857b21ec5559f0a9ef9d0e96f (diff) | |
download | scala-11398dd393fe3eff544bfbafafb584d3acd66e05.tar.gz scala-11398dd393fe3eff544bfbafafb584d3acd66e05.tar.bz2 scala-11398dd393fe3eff544bfbafafb584d3acd66e05.zip |
Improved @tailrec error messages to specify the...
Improved @tailrec error messages to specify the reason. In the process
fixed old bug involving tail call transformation. Closes #3275, #2018.
Review by dragos.
Diffstat (limited to 'test')
-rw-r--r-- | test/files/neg/tailrec.check | 18 | ||||
-rw-r--r-- | test/files/neg/tailrec.scala | 44 | ||||
-rw-r--r-- | test/files/pos/bug2018.scala | 15 |
3 files changed, 55 insertions, 22 deletions
diff --git a/test/files/neg/tailrec.check b/test/files/neg/tailrec.check index 22d70e82a0..27d99f632e 100644 --- a/test/files/neg/tailrec.check +++ b/test/files/neg/tailrec.check @@ -1,10 +1,16 @@ -tailrec.scala:6: error: could not optimize @tailrec annotated method +tailrec.scala:43: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position def facfail(n: Int): Int = ^ -tailrec.scala:42: error: could not optimize @tailrec annotated method +tailrec.scala:50: error: could not optimize @tailrec annotated method: it is neither private nor final so can be overridden @tailrec def fail1(x: Int): Int = fail1(x) ^ -tailrec.scala:45: error: could not optimize @tailrec annotated method - @tailrec def fail2[T](xs: List[T]): List[T] = xs match { - ^ -three errors found +tailrec.scala:53: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position + @tailrec final def fail2[T](xs: List[T]): List[T] = xs match { + ^ +tailrec.scala:59: error: could not optimize @tailrec annotated method: it is called recursively with different type arguments + @tailrec final def fail3[T](x: Int): Int = fail3(x - 1) + ^ +tailrec.scala:63: error: could not optimize @tailrec annotated method: it changes type of 'this' on a polymorphic recursive call + @tailrec final def fail4[U](other: Tom[U], x: Int): Int = other.fail4[U](other, x - 1) + ^ +5 errors found diff --git a/test/files/neg/tailrec.scala b/test/files/neg/tailrec.scala index 4c45672f93..a77f439cfe 100644 --- a/test/files/neg/tailrec.scala +++ b/test/files/neg/tailrec.scala @@ -1,53 +1,65 @@ import scala.annotation.tailrec // putting @tailrec through the paces -object Main { - @tailrec - def facfail(n: Int): Int = - if (n == 0) 1 - else n * facfail(n - 1) - +object Winners { @tailrec def facsucc(n: Int, acc: Int): Int = if (n == 0) acc else facsucc(n - 1, n * acc) - @tailrec def loopy1(x: Int): Int = loopy1(x - 1) + @tailrec def loopsucc1(x: Int): Int = loopsucc1(x - 1) + @tailrec def loopsucc2[T](x: Int): Int = loopsucc2[T](x - 1) def ding { object dong { - @tailrec def loopy2(x: Int): Int = loopy2(x) + @tailrec def loopsucc3(x: Int): Int = loopsucc3(x) } () } def inner(q: Int) = { @tailrec - def loopy3(x: Int): Int = loopy3(x + 1) + def loopsucc4(x: Int): Int = loopsucc4(x + 1) - loopy3(q) + loopsucc4(q) + } + + object innerBob { + @tailrec def loopsucc5(x: Int): Int = loopsucc5(x) } } -class Bob { - // these should work +class Winners { @tailrec private def succ1(x: Int): Int = succ1(x) @tailrec final def succ2(x: Int): Int = succ2(x) @tailrec final def succ3[T](in: List[T], acc: List[T]): List[T] = in match { case Nil => Nil case x :: xs => succ3(xs, x :: acc) } +} +object Failures { + @tailrec + def facfail(n: Int): Int = + if (n == 0) 1 + else n * facfail(n - 1) +} + +class Failures { // not private, not final @tailrec def fail1(x: Int): Int = fail1(x) // a typical between-chair-and-keyboard error - @tailrec def fail2[T](xs: List[T]): List[T] = xs match { + @tailrec final def fail2[T](xs: List[T]): List[T] = xs match { case Nil => Nil - case x :: xs => x :: fail2(xs) + case x :: xs => x :: fail2[T](xs) } - object innerBob { - @tailrec def succ4(x: Int): Int = succ4(x) + // unsafe + @tailrec final def fail3[T](x: Int): Int = fail3(x - 1) + + // unsafe + class Tom[T](x: Int) { + @tailrec final def fail4[U](other: Tom[U], x: Int): Int = other.fail4[U](other, x - 1) } } diff --git a/test/files/pos/bug2018.scala b/test/files/pos/bug2018.scala new file mode 100644 index 0000000000..1736c394c9 --- /dev/null +++ b/test/files/pos/bug2018.scala @@ -0,0 +1,15 @@ +class A { + val b = new B + + def getChildren = List(new A).iterator + + class B { + private def check = true + + private def getAncestor(p: A): A = { + val c = (p.getChildren.find(_.b.check)) match {case Some(d) => d case None => p} + + if (c == p) p else c.b.getAncestor(c) + } + } +}
\ No newline at end of file |