summaryrefslogtreecommitdiff
path: root/test/files/pos/t6479.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-01-13 15:07:31 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-01-13 15:07:31 +0100
commit9cc61f310ef5f80e598956bee20156b7bc472e84 (patch)
tree0da170845b4e73f43cd66e9072ac0a93bc7b7058 /test/files/pos/t6479.scala
parent5d65772762072aa950a488c666673dc248b01d6d (diff)
downloadscala-9cc61f310ef5f80e598956bee20156b7bc472e84.tar.gz
scala-9cc61f310ef5f80e598956bee20156b7bc472e84.tar.bz2
scala-9cc61f310ef5f80e598956bee20156b7bc472e84.zip
SI-6479 Don't lift try exprs in label arguments.
The new pattern matcher uses label jumps to GOTO the next case. Uncurry treated these like regular method arguments, and performed the liftedTree() transformation, which ensures that try expressions are only used in a statement position. Even try in statement position of a block used as such an argument are subject to the same transform. This transform stems from the JVM limitation, that try/catch does not leave a value on the stack. See b194446. This commit changes Uncurry to avoid this transform for arguments to label jumps. This avoids needlessly indirect code, and enables tail call elimination in more cases. As an example, Scala 2.10.0 transforms the last method of the enclosed test case to: try { case <synthetic> val x1: Int = 1; case5(){ if (2.==(x1)) { val x2: Int = x1; matchEnd4({ { def liftedTree2(): Unit = try { throw new scala.runtime.NonLocalReturnControl[Unit](nonLocalReturnKey1, ()) } catch { case (e @ (_: ClassNotFoundException)) => () }; liftedTree2() }; TailrecAfterTryCatch.this.bad() }) } else case6() }; case6(){ matchEnd4(throw new MatchError(x1)) }; matchEnd4(x: Unit){ x } } catch { case (ex @ (_: scala.runtime.NonLocalReturnControl[Unit @unchecked])) => if (ex.key().eq(nonLocalReturnKey1)) ex.value() else throw ex } After this patch: @scala.annotation.tailrec final def bad(): Unit = { case <synthetic> val x1: Int = 1; case5(){ if (2.==(x1)) { <synthetic> val x2: Int = x1; matchEnd4({ try { return () } catch { case (e @ (_: ClassNotFoundException)) => () }; TailrecAfterTryCatch.this.bad() }) } else case6() }; case6(){ matchEnd4(throw new MatchError(x1)) }; matchEnd4(x: Unit){ x } }
Diffstat (limited to 'test/files/pos/t6479.scala')
-rw-r--r--test/files/pos/t6479.scala56
1 files changed, 56 insertions, 0 deletions
diff --git a/test/files/pos/t6479.scala b/test/files/pos/t6479.scala
new file mode 100644
index 0000000000..c463bc5ab0
--- /dev/null
+++ b/test/files/pos/t6479.scala
@@ -0,0 +1,56 @@
+object TailrecAfterTryCatch {
+
+ @annotation.tailrec
+ final def good1() {
+ 1 match {
+ case 2 => {
+ try {
+ // return
+ } catch {
+ case e: ClassNotFoundException =>
+ }
+ good1()
+ }
+ }
+ }
+
+ @annotation.tailrec
+ final def good2() {
+ //1 match {
+ // case 2 => {
+ try {
+ return
+ } catch {
+ case e: ClassNotFoundException =>
+ }
+ good2()
+ // }
+ //}
+ }
+
+ @annotation.tailrec
+ final def good3() {
+ val 1 = 2
+ try {
+ return
+ } catch {
+ case e: ClassNotFoundException =>
+ }
+ good3()
+ }
+
+ @annotation.tailrec
+ final def bad() {
+ 1 match {
+ case 2 => {
+ try {
+ return
+ } catch {
+ case e: ClassNotFoundException =>
+ }
+ bad()
+ }
+ }
+ }
+
+} \ No newline at end of file