diff options
author | Paul Phillips <paulp@improving.org> | 2010-07-02 04:20:44 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-07-02 04:20:44 +0000 |
commit | fbc453397552983a2c2a229cca8f7c13a641b9c7 (patch) | |
tree | ed5101b5693e52f7e8160e3bc7b38ed70ddf3892 /src/compiler | |
parent | 58adc8d999687d1cfa6394d7f4201dfaf411ccfe (diff) | |
download | scala-fbc453397552983a2c2a229cca8f7c13a641b9c7.tar.gz scala-fbc453397552983a2c2a229cca8f7c13a641b9c7.tar.bz2 scala-fbc453397552983a2c2a229cca8f7c13a641b9c7.zip |
Some more improvement on the error messages whe...
Some more improvement on the error messages when @tailrec fails. Now it
gives a sensible message if the recursive target is actually a supertype
of this, rather than saying the call is not in tail position. No review.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/TailCalls.scala | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 9b54dd9428..c7a3e6a778 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -102,7 +102,7 @@ abstract class TailCalls extends Transform var tailPos = false /** The reason this method could not be optimized. */ - var tailrecFailReason = "it contains a recursive call not in tail position" + var tailrecFailReason = "reason indeterminate" /** Is the label accessed? */ var accessed = false @@ -153,6 +153,13 @@ abstract class TailCalls extends Transform /** A possibly polymorphic apply to be considered for tail call transformation. */ def rewriteApply(target: Tree, fun: Tree, targs: List[Tree], args: List[Tree]) = { + def receiver = fun match { + case Select(qual, _) => Some(qual) + case _ => None + } + + def receiverIsSame = receiver exists (enclosingType.widen =:= _.tpe.widen) + def receiverIsSuper = receiver exists (enclosingType.widen <:< _.tpe.widen) def isRecursiveCall = ctx.currentMethod eq fun.symbol def isMandatory = ctx.currentMethod hasAnnotation TailrecClass def isEligible = ctx.currentMethod.isEffectivelyFinal @@ -160,9 +167,6 @@ abstract class TailCalls extends Transform def matchesTypeArgs = ctx.tparams sameElements (targs map (_.tpe.typeSymbol)) def defaultTree = treeCopy.Apply(tree, target, transformArgs) - def sameTypeOfThis(receiver: Tree) = - receiver.tpe.widen =:= enclosingType.widen - /** Records failure reason in Context for reporting. */ def cannotRewrite(reason: String) = { @@ -171,6 +175,10 @@ abstract class TailCalls extends Transform defaultTree } + def notRecursiveReason() = + if (receiverIsSuper) "it contains a recursive call targetting a supertype" + else "it contains a recursive call not in tail position" + def rewriteTailCall(receiver: Tree, otherArgs: List[Tree]): Tree = { log("Rewriting tail recursive method call at: " + fun.pos) @@ -178,15 +186,16 @@ abstract class TailCalls extends Transform typed { atPos(fun.pos)(Apply(Ident(ctx.label), receiver :: otherArgs)) } } - if (!isRecursiveCall) defaultTree + if (!isRecursiveCall) cannotRewrite(notRecursiveReason()) else if (!isEligible) cannotRewrite("it is neither private nor final so can be overridden") else if (!ctx.tailPos) cannotRewrite("it contains a recursive call not in tail position") else if (!matchesTypeArgs) cannotRewrite("it is called recursively with different type arguments") - else fun match { - case Select(_, _) if forMSIL => cannotRewrite("it cannot be optimized on MSIL") - case Select(qual, _) if !sameTypeOfThis(qual) => cannotRewrite("it changes type of 'this' on a polymorphic recursive call") - case Select(qual, _) => rewriteTailCall(qual, transformArgs) - case _ => rewriteTailCall(This(currentClass), transformArgs) + else receiver match { + case Some(qual) => + if (forMSIL) cannotRewrite("it cannot be optimized on MSIL") + else if (!receiverIsSame) cannotRewrite("it changes type of 'this' on a polymorphic recursive call") + else rewriteTailCall(qual, transformArgs) + case _ => rewriteTailCall(This(currentClass), transformArgs) } } |