Skip to content

Commit 051f6a6

Browse files
Merge pull request #7038 from dotty-staging/add-rescue
Add rescue to support streamline error handling
2 parents 9ab6c67 + d31a8bb commit 051f6a6

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

tests/run/rescue.scala

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import scala.util.control.NonFatal
2+
import scala.util.control.NonLocalReturns._
3+
4+
object lib {
5+
inline def (op: => T) rescue[T] (fallback: => T) =
6+
try op
7+
catch {
8+
case NonFatal(_) => fallback // ReturnThrowable is fatal error, thus ignored
9+
}
10+
11+
inline def (op: => T) rescue[T, E <: Throwable] (fallback: PartialFunction[E, T]) =
12+
try op
13+
catch {
14+
// case ex: ReturnThrowable[_] => throw ex // bug #7041
15+
case ex: E =>
16+
// user should never match `ReturnThrowable`, which breaks semantics of non-local return
17+
if (fallback.isDefinedAt(ex) && !ex.isInstanceOf[ReturnThrowable[_]]) fallback(ex) else throw ex
18+
}
19+
}
20+
21+
import lib._
22+
23+
@main def Test = {
24+
assert((9 / 1 rescue 1) == 9)
25+
assert((9 / 0 rescue 1) == 1)
26+
assert(((9 / 0 rescue { case ex: NullPointerException => 5 }) rescue 10) == 10)
27+
assert(((9 / 0 rescue { case ex: ArithmeticException => 5 }) rescue 10) == 5)
28+
29+
assert(
30+
{
31+
9 / 0 rescue {
32+
case ex: NullPointerException => 4
33+
case ex: ArithmeticException => 3
34+
}
35+
} == 3
36+
)
37+
38+
(9 / 0) rescue { case ex: ArithmeticException => 4 }
39+
40+
assert(
41+
{
42+
{
43+
val a = 9 / 0 rescue {
44+
case ex: NullPointerException => 4
45+
}
46+
a * a
47+
} rescue {
48+
case ex: ArithmeticException => 3
49+
}
50+
} == 3
51+
)
52+
53+
assert(foo(10) == 40)
54+
assert(bar(10) == 40)
55+
56+
// should not catch fatal errors
57+
assert(
58+
try { { throw new OutOfMemoryError(); true } rescue false }
59+
catch { case _: OutOfMemoryError => true }
60+
)
61+
62+
// should catch any errors specified, including fatal errors
63+
assert(
64+
try { { throw new OutOfMemoryError(); true } rescue { case _: OutOfMemoryError => true } }
65+
catch { case _: OutOfMemoryError => false }
66+
)
67+
68+
// should not catch NonLocalReturns
69+
def foo(x: Int): Int = returning[Int] {
70+
{ throwReturn[Int](4 * x) : Int } rescue 10
71+
}
72+
73+
// should catch specified exceptions, but not NonLocalReturn
74+
def bar(x: Int): Int = returning[Int] {
75+
{ throwReturn[Int](4 * x) : Int } rescue { case _ => 10 }
76+
}
77+
78+
}

0 commit comments

Comments
 (0)