blob: 332e6e7585cc8d9ecb54bb56983aac543021b70f [file] [log] [blame] [edit]
-- Test cases for exception handling insertion transform.
--
-- The result includes refcount handling since these two transforms interact.
[case testListGetAndUnboxError]
from typing import List
def f(x: List[int]) -> int:
return x[0]
[out]
def f(x):
x :: list
r0 :: short_int
r1 :: object
r2, r3 :: int
L0:
r0 = 0
r1 = x[r0] :: list
if is_error(r1) goto L3 (error at f:3) else goto L1
L1:
r2 = unbox(int, r1)
dec_ref r1
if is_error(r2) goto L3 (error at f:3) else goto L2
L2:
return r2
L3:
r3 = <error> :: int
return r3
[case testListAppendAndSetItemError]
from typing import List
def f(x: List[int], y: int, z: int) -> None:
x.append(y)
x[y] = z
[out]
def f(x, y, z):
x :: list
y, z :: int
r0 :: object
r1 :: bool
r2 :: None
r3 :: object
r4 :: bool
r5, r6 :: None
L0:
inc_ref y :: int
r0 = box(int, y)
r1 = x.append(r0) :: list
dec_ref r0
if not r1 goto L3 (error at f:3) else goto L1 :: bool
L1:
r2 = None
inc_ref z :: int
r3 = box(int, z)
r4 = x.__setitem__(y, r3) :: list
if not r4 goto L3 (error at f:4) else goto L2 :: bool
L2:
r5 = None
return r5
L3:
r6 = <error> :: None
return r6
[case testOptionalHandling]
from typing import Optional
class A: pass
def f(x: Optional[A]) -> int:
if x is None:
return 1
if x is not None:
return 2
return 3
[out]
def f(x):
x :: union[__main__.A, None]
r0 :: None
r1 :: object
r2 :: bool
r3 :: short_int
r4 :: __main__.A
r5 :: None
r6 :: object
r7, r8 :: bool
r9, r10 :: short_int
r11 :: int
L0:
r0 = None
r1 = box(None, r0)
r2 = x is r1
if r2 goto L1 else goto L2 :: bool
L1:
r3 = 1
return r3
L2:
inc_ref x
r4 = cast(__main__.A, x)
if is_error(r4) goto L6 (error at f:8) else goto L3
L3:
r5 = None
r6 = box(None, r5)
r7 = r4 is r6
dec_ref r4
r8 = !r7
if r8 goto L4 else goto L5 :: bool
L4:
r9 = 2
return r9
L5:
r10 = 3
return r10
L6:
r11 = <error> :: int
return r11
[case testListSum]
from typing import List
def sum(a: List[int], l: int) -> int:
sum = 0
i = 0
while i < l:
sum = sum + a[i]
i = i + 1
return sum
[out]
def sum(a, l):
a :: list
l :: int
r0 :: short_int
sum :: int
r1 :: short_int
i :: int
r2 :: bool
r3 :: object
r4, r5 :: int
r6 :: short_int
r7, r8 :: int
L0:
r0 = 0
sum = r0
r1 = 0
i = r1
L1:
r2 = i < l :: int
if r2 goto L2 else goto L7 :: bool
L2:
r3 = a[i] :: list
if is_error(r3) goto L8 (error at sum:6) else goto L3
L3:
r4 = unbox(int, r3)
dec_ref r3
if is_error(r4) goto L8 (error at sum:6) else goto L4
L4:
r5 = sum + r4 :: int
dec_ref sum :: int
dec_ref r4 :: int
sum = r5
r6 = 1
r7 = i + r6 :: int
dec_ref i :: int
i = r7
goto L1
L5:
return sum
L6:
r8 = <error> :: int
return r8
L7:
dec_ref i :: int
goto L5
L8:
dec_ref sum :: int
dec_ref i :: int
goto L6
[case testTryExcept]
def g() -> None:
try:
object()
except:
print("weeee")
[out]
def g():
r0 :: object
r1 :: str
r2, r3 :: object
r4 :: tuple[object, object, object]
r5 :: str
r6 :: object
r7 :: str
r8, r9 :: object
r10 :: bool
r11, r12 :: None
L0:
L1:
r0 = builtins :: module
r1 = unicode_1 :: static ('object')
r2 = getattr r0, r1
if is_error(r2) goto L3 (error at g:3) else goto L2
L2:
r3 = py_call(r2)
dec_ref r2
if is_error(r3) goto L3 (error at g:3) else goto L10
L3:
r4 = error_catch
r5 = unicode_2 :: static ('weeee')
r6 = builtins :: module
r7 = unicode_3 :: static ('print')
r8 = getattr r6, r7
if is_error(r8) goto L6 (error at g:5) else goto L4
L4:
r9 = py_call(r8, r5)
dec_ref r8
if is_error(r9) goto L6 (error at g:5) else goto L11
L5:
restore_exc_info r4
dec_ref r4
goto L8
L6:
restore_exc_info r4
dec_ref r4
r10 = keep_propagating
if not r10 goto L9 else goto L7 :: bool
L7:
unreachable
L8:
r11 = None
return r11
L9:
r12 = <error> :: None
return r12
L10:
dec_ref r3
goto L8
L11:
dec_ref r9
goto L5
[case testGenopsTryFinally]
def a() -> str:
try:
print()
return 'hi'
finally:
print('goodbye!')
[out]
def a():
r0 :: object
r1 :: str
r2, r3 :: object
r4, r5 :: str
r6 :: tuple[object, object, object]
r7 :: str
r8 :: tuple[object, object, object]
r9 :: str
r10 :: tuple[object, object, object]
r11 :: str
r12 :: object
r13 :: str
r14, r15 :: object
r16, r17 :: bool
r18 :: str
L0:
L1:
r0 = builtins :: module
r1 = unicode_1 :: static ('print')
r2 = getattr r0, r1
if is_error(r2) goto L5 (error at a:3) else goto L2
L2:
r3 = py_call(r2)
dec_ref r2
if is_error(r3) goto L5 (error at a:3) else goto L20
L3:
r4 = unicode_2 :: static ('hi')
inc_ref r4
r5 = r4
L4:
r8 = <error> :: tuple[object, object, object]
r6 = r8
goto L6
L5:
r9 = <error> :: str
r5 = r9
r10 = error_catch
r6 = r10
L6:
r11 = unicode_3 :: static ('goodbye!')
r12 = builtins :: module
r13 = unicode_1 :: static ('print')
r14 = getattr r12, r13
if is_error(r14) goto L13 (error at a:6) else goto L7
L7:
r15 = py_call(r14, r11)
dec_ref r14
if is_error(r15) goto L13 (error at a:6) else goto L21
L8:
if is_error(r6) goto L11 else goto L9
L9:
reraise_exc; r16 = 0
if not r16 goto L13 else goto L22 :: bool
L10:
unreachable
L11:
if is_error(r5) goto L18 else goto L12
L12:
return r5
L13:
if is_error(r5) goto L14 else goto L23
L14:
if is_error(r6) goto L16 else goto L15
L15:
restore_exc_info r6
dec_ref r6
L16:
r17 = keep_propagating
if not r17 goto L19 else goto L17 :: bool
L17:
unreachable
L18:
unreachable
L19:
r18 = <error> :: str
return r18
L20:
dec_ref r3
goto L3
L21:
dec_ref r15
goto L8
L22:
dec_ref r5
dec_ref r6
goto L10
L23:
dec_ref r5
goto L14
[case testDocstring1]
def lol() -> None:
"""Hello"""
pass
[out]
def lol():
r0 :: None
L0:
r0 = None
return r0
[case testExceptUndefined1]
from typing import Any
def lol(x: Any) -> object:
try:
st = x.foo
except:
return ''
# No uninit check should be generated, since the exception branch always returns
return st
[out]
def lol(x):
x :: object
r0 :: str
r1, st :: object
r2 :: tuple[object, object, object]
r3 :: str
r4 :: bool
r5 :: object
L0:
L1:
r0 = unicode_3 :: static ('foo')
r1 = getattr x, r0
if is_error(r1) goto L3 (error at lol:4) else goto L2
L2:
st = r1
goto L4
L3:
r2 = error_catch
r3 = unicode_4 :: static
restore_exc_info r2
dec_ref r2
inc_ref r3
return r3
L4:
return st
[case testExceptUndefined2]
from typing import Any
def lol(x: Any) -> object:
try:
a = x.foo
b = x.bar
except:
pass
# uninit checks are needed, since the exception can skip initializing the vars
return a + b
[out]
def lol(x):
x :: object
r0 :: str
r1, a :: object
r2 :: str
r3, b :: object
r4 :: tuple[object, object, object]
r5 :: bool
r6 :: object
r7, r8 :: bool
r9 :: object
L0:
L1:
r0 = unicode_3 :: static ('foo')
r1 = getattr x, r0
if is_error(r1) goto L4 (error at lol:4) else goto L15
L2:
a = r1
r2 = unicode_4 :: static ('bar')
r3 = getattr x, r2
if is_error(r3) goto L4 (error at lol:5) else goto L16
L3:
b = r3
goto L6
L4:
r4 = error_catch
L5:
restore_exc_info r4
dec_ref r4
L6:
if is_error(a) goto L17 else goto L9
L7:
raise UnboundLocalError("local variable 'a' referenced before assignment")
if not r7 goto L14 (error at lol:9) else goto L8 :: bool
L8:
unreachable
L9:
if is_error(b) goto L18 else goto L12
L10:
raise UnboundLocalError("local variable 'b' referenced before assignment")
if not r8 goto L14 (error at lol:9) else goto L11 :: bool
L11:
unreachable
L12:
r6 = a + b
xdec_ref a
xdec_ref b
if is_error(r6) goto L14 (error at lol:9) else goto L13
L13:
return r6
L14:
r9 = <error> :: object
return r9
L15:
xdec_ref a
goto L2
L16:
xdec_ref b
goto L3
L17:
xdec_ref b
goto L7
L18:
xdec_ref a
goto L10
[case testMaybeUninitVarExc]
def f(b: bool) -> None:
u = 'a'
while b:
v = 'b'
if v is not u:
break
print(v)
[out]
def f(b):
b :: bool
r0, u, r1, v :: str
r2, r3 :: bool
r4 :: object
r5 :: str
r6, r7 :: object
r8 :: None
r9 :: bool
r10 :: None
L0:
r0 = unicode_1 :: static ('a')
inc_ref r0
u = r0
L1:
if b goto L10 else goto L11 :: bool
L2:
r1 = unicode_2 :: static ('b')
inc_ref r1
v = r1
r2 = v is u
r3 = !r2
if r3 goto L11 else goto L1 :: bool
L3:
r4 = builtins :: module
r5 = unicode_3 :: static ('print')
r6 = getattr r4, r5
if is_error(r6) goto L12 (error at f:7) else goto L4
L4:
if is_error(v) goto L13 else goto L7
L5:
raise UnboundLocalError("local variable 'v' referenced before assignment")
if not r9 goto L9 (error at f:7) else goto L6 :: bool
L6:
unreachable
L7:
r7 = py_call(r6, v)
dec_ref r6
xdec_ref v
if is_error(r7) goto L9 (error at f:7) else goto L14
L8:
r8 = None
return r8
L9:
r10 = <error> :: None
return r10
L10:
xdec_ref v
goto L2
L11:
dec_ref u
goto L3
L12:
xdec_ref v
goto L9
L13:
dec_ref r6
goto L5
L14:
dec_ref r7
goto L8