scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

@tailrec fails on polymorphic recursion (correctly), but this is hidden by spurious error #5814

Open scabug opened 12 years ago

scabug commented 12 years ago

I apologize for non reducing the bug yet, I can do it if needed. Scenario: I mark a tail-recursive function with @tailrec, but when I compile it I get the wrong reason why it cannot be optimized: it complains that the base case (non-recursive) is a recursive call not in tail position! If I comment out this call and replace it with a value, I get a more reasonable error: this function in fact uses polymorphic tail-recursion, which according to the error is not supported (which is kind-of fine, even though in principle it should be easy to support that case as well*). Making the call non-polymorphic fixes indeed the problem.

Example: Concretely, the code is the following:

  @tailrec private def usesArgAtMostOnce[S, T](f: Fun[S, T], v: Exp[_]): Boolean = {
    f match {
      case FuncExpBody(FlatMap(ExpSeq(Seq(v2)), g)) if !v2.isOrContains(v) =>
        usesArgAtMostOnce(g, v)
      case FuncExpBody(FlatMap(baseUsingV, g)) =>
        val occurrences = baseUsingV.findTotFun(_ == v) //XXX check occurrences.
        occurrences.length == 1
        //false
      case _ => false
    }

And the error is the following:

/Users/pgiarrusso/Documents/Research/Sorgenti/linqonsteroids/src/main/scala/ivm/optimization/Optimization.scala:542: could not optimize @tailrec annotated method usesArgAtMostOnce: it contains a recursive call not in tail position
[error]         occurrences.length == 1
[error]                            ^
[error] one error found

When I remove the polymorphic recursion, that code is accepted, hence the warning is as wrong as it seems. If I comment out that code location and simply return 'false' there, I get instead:


[error] /Users/pgiarrusso/Documents/Research/Sorgenti/linqonsteroids/src/main/scala/ivm/optimization/Optimization.scala:537: could not optimize @tailrec annotated method usesArgAtMostOnce: it is called recursively with different type arguments
[error]         usesArgAtMostOnce(g, v)
[error]         ^
[error] one error found

The errors are from 2.9.2, I got essentially the same behavior from 2.9.1.

Polymorphic tail-recursion should be easy to optimize. This optimization should happen after erasure, where type parameters are irrelevant; they can only become relevant through implicit parameters, but they can be treated equally to other parameters, so not even this case is a problem. I'm not sure whether there would be a problem before erasure, except that one would need to modify type arguments. But at least defining* tail recursion in F-omega-sub (F^omega<: ) doesn't seem to be any different from a system without polymorphism (STLC or lambda<: ).

scabug commented 12 years ago

Imported From: https://issues.scala-lang.org/browse/SI-5814?orig=1 Reporter: @Blaisorblade Affected Versions: 2.9.1, 2.9.2

scabug commented 12 years ago

@adriaanm said: could it simply be an error-reporting problem?

scabug commented 12 years ago

@Blaisorblade said: The main problem is an error-reporting problem, at least from the user's perspective (if you're asking me, not sure). [In the bug report I also ask about support for polymorphic recursion, but let's say that's a request for enhancement].

scabug commented 11 years ago

@JamesIry said: 2.10.2 is about to be cut. Kicking down the road and un-assigning to foster work stealing.