Skip to content

Commit d31a8bb

Browse files
committed
Only rescue non-fatal errors
However, with explict cases, user may match fatal errors except for non-local returns, which users should not catch.
1 parent 910f6b3 commit d31a8bb

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

tests/run/rescue.scala

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1+
import scala.util.control.NonFatal
2+
import scala.util.control.NonLocalReturns._
3+
14
object lib {
25
inline def (op: => T) rescue[T] (fallback: => T) =
36
try op
47
catch {
5-
case _: Throwable => fallback
8+
case NonFatal(_) => fallback // ReturnThrowable is fatal error, thus ignored
69
}
710

811
inline def (op: => T) rescue[T, E <: Throwable] (fallback: PartialFunction[E, T]) =
912
try op
1013
catch {
14+
// case ex: ReturnThrowable[_] => throw ex // bug #7041
1115
case ex: E =>
12-
if (fallback.isDefinedAt(ex)) fallback(ex) else throw ex
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
1318
}
1419
}
1520

@@ -30,6 +35,8 @@ import lib._
3035
} == 3
3136
)
3237

38+
(9 / 0) rescue { case ex: ArithmeticException => 4 }
39+
3340
assert(
3441
{
3542
{
@@ -42,4 +49,30 @@ import lib._
4249
}
4350
} == 3
4451
)
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+
4578
}

0 commit comments

Comments
 (0)