Skip to content
This repository was archived by the owner on Jul 12, 2024. It is now read-only.

Commit 3da9ca2

Browse files
committed
Fix #101: Interaction between TryFinally and Labeled/Return.
See the big "HERE BE DRAGONS" comment for details.
1 parent bfc35ac commit 3da9ca2

File tree

5 files changed

+738
-88
lines changed

5 files changed

+738
-88
lines changed

Diff for: build.sbt

-2
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,6 @@ lazy val IgnoredTestNames: Set[String] = {
236236
"org.scalajs.testsuite.javalib.lang.ThrowableJSTest",
237237
// jsError/jsObject failed: AssertionError because Wasm objects are not instanceof Error/Object
238238
"org.scalajs.testsuite.compiler.RuntimeTypeTestsJSTest",
239-
// keepBreakToLabelWithinFinallyBlock_Issue2689 failed: java.lang.AssertionError: expected:<2> but was:<1>
240-
"org.scalajs.testsuite.compiler.OptimizerTest",
241239
// No support for stack traces
242240
"org.scalajs.testsuite.library.StackTraceTest",
243241
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
package testsuite.core
2+
3+
import testsuite.Assert.assertSame
4+
5+
/** Imported from the Scala test case `test/files/run/finally.scala`. */
6+
object TryFinallyReturnTest {
7+
// Simulate a `println` API that we can check afterwards
8+
var printlnOutput: String = ""
9+
10+
def println(x: Any): Unit =
11+
printlnOutput = printlnOutput + x + "\n"
12+
13+
val expectedOutput = raw"""Running throwCatchFinally
14+
hi
15+
In Finally
16+
java.lang.RuntimeException: ouch
17+
----------------------------------------
18+
Running retCatch
19+
java.lang.Exception
20+
in finally
21+
----------------------------------------
22+
Running throwCatch
23+
java.lang.Exception
24+
in finally
25+
CAUGHT: java.lang.Exception
26+
----------------------------------------
27+
Running retBody
28+
in finally
29+
----------------------------------------
30+
Running throwBody
31+
java.lang.Exception
32+
in finally
33+
----------------------------------------
34+
Running retFinally
35+
body
36+
in finally 1
37+
in finally 2
38+
----------------------------------------
39+
Running throwFinally
40+
body
41+
in finally
42+
java.lang.Exception
43+
----------------------------------------
44+
Running nestedFinallyBlocks
45+
in finally 1
46+
in finally 2
47+
----------------------------------------
48+
Running nestedFinallyBlocks2
49+
in try 1
50+
in finally 1
51+
in fall-through
52+
in finally 2
53+
----------------------------------------
54+
"""
55+
56+
def main(): Unit = {
57+
test(throwCatchFinally(), "throwCatchFinally")
58+
test(retCatch(), "retCatch")
59+
test(throwCatch(), "throwCatch")
60+
test(retBody(), "retBody")
61+
test(throwBody(), "throwBody")
62+
test(retFinally(), "retFinally")
63+
test(throwFinally(), "throwFinally")
64+
test(nestedFinallyBlocks(), "nestedFinallyBlocks")
65+
test(nestedFinallyBlocks2(), "nestedFinallyBlocks2")
66+
67+
assertSame(expectedOutput, printlnOutput)
68+
}
69+
70+
// test that finally is not covered by any exception handlers.
71+
def throwCatchFinally(): Unit = {
72+
try {
73+
bar()
74+
} catch {
75+
case e: Throwable => println(e)
76+
}
77+
}
78+
79+
// test that finally is not covered by any exception handlers.
80+
def bar(): Unit = {
81+
try {
82+
println("hi")
83+
} catch {
84+
case e: Throwable => println("SHOULD NOT GET HERE")
85+
} finally {
86+
println("In Finally")
87+
throw new RuntimeException("ouch")
88+
}
89+
}
90+
91+
// return in catch (finally is executed)
92+
def retCatch(): Unit = {
93+
try {
94+
throw new Exception
95+
} catch {
96+
case e: Throwable =>
97+
println(e);
98+
return
99+
} finally println("in finally")
100+
}
101+
102+
// throw in catch (finally is executed, exception propagated)
103+
def throwCatch(): Unit = {
104+
try {
105+
throw new Exception
106+
} catch {
107+
case e: Throwable =>
108+
println(e);
109+
throw e
110+
} finally println("in finally")
111+
}
112+
113+
// return inside body (finally is executed)
114+
def retBody(): Unit = {
115+
try {
116+
return
117+
} catch {
118+
case e: Throwable =>
119+
println(e);
120+
throw e
121+
} finally println("in finally")
122+
}
123+
124+
// throw inside body (finally and catch are executed)
125+
def throwBody(): Unit = {
126+
try {
127+
throw new Exception
128+
} catch {
129+
case e: Throwable =>
130+
println(e);
131+
} finally println("in finally")
132+
}
133+
134+
// return inside finally (each finally is executed once)
135+
def retFinally(): Unit = {
136+
try {
137+
try println("body")
138+
finally {
139+
println("in finally 1")
140+
return
141+
}
142+
} finally println("in finally 2")
143+
}
144+
145+
// throw inside finally (finally is executed once, exception is propagated)
146+
def throwFinally(): Unit = {
147+
try {
148+
try println("body")
149+
finally {
150+
println("in finally")
151+
throw new Exception
152+
}
153+
} catch {
154+
case e: Throwable => println(e)
155+
}
156+
}
157+
158+
// nested finally blocks with return value
159+
def nestedFinallyBlocks(): Int =
160+
try {
161+
try {
162+
return 10
163+
} finally {
164+
try { () }
165+
catch { case _: Throwable => () }
166+
println("in finally 1")
167+
}
168+
} finally {
169+
println("in finally 2")
170+
}
171+
172+
def nestedFinallyBlocks2(): Int = {
173+
try {
174+
try {
175+
println("in try 1")
176+
} finally {
177+
println("in finally 1")
178+
}
179+
println("in fall-through")
180+
0
181+
} finally {
182+
println("in finally 2")
183+
}
184+
}
185+
186+
def test[A](m: => A, name: String): Unit = {
187+
println("Running %s".format(name))
188+
try {
189+
m
190+
} catch {
191+
case e: Throwable => println("CAUGHT: " + e)
192+
}
193+
println("-" * 40)
194+
}
195+
}

Diff for: tests/src/test/scala/tests/TestSuites.scala

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ object TestSuites {
4040
TestSuite("testsuite.core.StaticMethodTest"),
4141
TestSuite("testsuite.core.ThrowAndTryTest"),
4242
TestSuite("testsuite.core.ThrowablesTest"),
43+
TestSuite("testsuite.core.TryFinallyReturnTest"),
4344
TestSuite("testsuite.core.ToStringTest"),
4445
TestSuite("testsuite.core.UnitPatMatTest"),
4546
TestSuite("testsuite.core.MatchTest"),

0 commit comments

Comments
 (0)