summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-03-22 10:39:29 +0100
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-03-23 11:03:02 +0100
commitd786f269834c89e6de4a6a90e7a9f22c583bc30a (patch)
tree06c68ba36971b81799094856c6d22eb3cce6abfb
parentf8022c216d84af482b27c04c3c38a2d8dce9a192 (diff)
downloadscala-d786f269834c89e6de4a6a90e7a9f22c583bc30a.tar.gz
scala-d786f269834c89e6de4a6a90e7a9f22c583bc30a.tar.bz2
scala-d786f269834c89e6de4a6a90e7a9f22c583bc30a.zip
[vpm] avoid verifyerror: leave jump to tail-pos label
the following commit deals with the fall-out in basicblocks (double closing of blocks in ignore mode)
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala9
-rw-r--r--test/files/run/virtpatmat_tailcalls_verifyerror.check1
-rw-r--r--test/files/run/virtpatmat_tailcalls_verifyerror.flags1
-rw-r--r--test/files/run/virtpatmat_tailcalls_verifyerror.scala13
4 files changed, 22 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index ef76fe1b1c..9915f7e9fc 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -341,13 +341,18 @@ abstract class TailCalls extends Transform {
else if (fun.symbol.isLabel && args.nonEmpty && args.tail.isEmpty && ctx.tailLabels(fun.symbol)) {
// this is to detect tailcalls in translated matches
// it's a one-argument call to a label that is in a tailposition and that looks like label(x) {x}
- // thus, the argument to the call is in tailposition and we don't need to jump to the label, tail jump instead
+ // thus, the argument to the call is in tailposition
val saved = ctx.tailPos
ctx.tailPos = true
debuglog("in tailpos label: "+ args.head)
val res = transform(args.head)
ctx.tailPos = saved
- if (res ne args.head) res // we tail-called -- TODO: shield from false-positives where we rewrite but don't tail-call
+ if (res ne args.head) {
+ // we tail-called -- TODO: shield from false-positives where we rewrite but don't tail-call
+ // must leave the jump to the original tailpos-label (fun)!
+ // there might be *a* tailcall *in* res, but it doesn't mean res *always* tailcalls
+ treeCopy.Apply(tree, fun, List(res))
+ }
else rewriteApply(fun, fun, Nil, args)
} else rewriteApply(fun, fun, Nil, args)
diff --git a/test/files/run/virtpatmat_tailcalls_verifyerror.check b/test/files/run/virtpatmat_tailcalls_verifyerror.check
new file mode 100644
index 0000000000..c508d5366f
--- /dev/null
+++ b/test/files/run/virtpatmat_tailcalls_verifyerror.check
@@ -0,0 +1 @@
+false
diff --git a/test/files/run/virtpatmat_tailcalls_verifyerror.flags b/test/files/run/virtpatmat_tailcalls_verifyerror.flags
new file mode 100644
index 0000000000..9769db9257
--- /dev/null
+++ b/test/files/run/virtpatmat_tailcalls_verifyerror.flags
@@ -0,0 +1 @@
+ -Yvirtpatmat -Xexperimental
diff --git a/test/files/run/virtpatmat_tailcalls_verifyerror.scala b/test/files/run/virtpatmat_tailcalls_verifyerror.scala
new file mode 100644
index 0000000000..1ee613f09e
--- /dev/null
+++ b/test/files/run/virtpatmat_tailcalls_verifyerror.scala
@@ -0,0 +1,13 @@
+// shouldn't result in a verify error when run...
+object Test extends App {
+ @annotation.tailrec
+ final def test(meh: Boolean): Boolean = {
+ Some("a") match {
+ case x =>
+ x match {
+ case _ => if(meh) test(false) else false
+ }
+ }
+ }
+ println(test(true))
+} \ No newline at end of file