summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala29
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)
}
}