-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pattern matching breaks @tailrec #10493
Comments
@Atry Your |
I guess the error here is in the error message. Should be: <console>:18: error: could not optimize @tailrec annotated method last: it contains a recursive call not in tail position
cons.last()
^ instead of: <console>:20: error: could not optimize @tailrec annotated method last: it contains a recursive call not in tail position
notCons
^ |
@jvican That's an assessment I'd second. |
Shouldn't the error rather be
when aiming low, or something like
when aiming high? |
scalac is in general perfectly capable of tailrec-transforming methods that call themselves on a different receiver than scala> trait Cons[A] {
| def next(): Any
|
| @scala.annotation.tailrec
| final def last(): Any = {
| val n = next()
| if (n.isInstanceOf[Cons[_]])
| n.asInstanceOf[Cons[_]].last()
| else
| n
| }
| }
<console>:14: error: could not optimize @tailrec annotated method last: it changes type of 'this' on a polymorphic recursive call
n.asInstanceOf[Cons[_]].last()
^ If we cheat and cast to scala> trait Cons[A] {
| def next(): Any
|
| @scala.annotation.tailrec
| final def last(): Any = {
| val n = next()
| if (n.isInstanceOf[Cons[_]])
| n.asInstanceOf[Cons[A]].last()
| else
| n
| }
| }
defined trait Cons |
@sjrd 👍 |
@sjrd I think it's a different problem. In the example that I provided, the error position is |
The position of the error is definitely off, but it is the problem I describe. You can also "fix" the problem with a scala> :paste
// Entering paste mode (ctrl-D to finish)
trait Cons[A] {
def next(): Any
@scala.annotation.tailrec
final private def last(): Any = {
next() match {
case cons: Cons[_] =>
cons.asInstanceOf[Cons[A]].last()
case notCons =>
notCons
}
}
}
// Exiting paste mode, now interpreting.
defined trait Cons |
scala/scala#6065 would allow a workaround: trait Cons[A] {
def next(): Any
def last(): Any = {
@scala.annotation.tailrec
def go[T](c: Cons[T]): Any =
c.next() match {
case cons: Cons[_] =>
go(cons)
case notCons =>
notCons
}
go(this)
}
} |
The text was updated successfully, but these errors were encountered: