Skip to content

Commit 212380b

Browse files
committed
Fix exceptions
1 parent 1e8c97e commit 212380b

File tree

4 files changed

+26
-7
lines changed

4 files changed

+26
-7
lines changed

mypyc/irbuild/nonlocalcontrol.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def gen_return(self, builder: IRBuilder, value: Value, line: int) -> None:
113113

114114
true, false = BasicBlock(), BasicBlock()
115115
stop_iter_reg = builder.fn_info.generator_class.stop_iter_value_reg
116+
assert stop_iter_reg is not None
116117

117118
builder.add(Branch(stop_iter_reg, true, false, Branch.IS_ERROR))
118119

@@ -124,9 +125,9 @@ def gen_return(self, builder: IRBuilder, value: Value, line: int) -> None:
124125
builder.builder.pop_error_handler()
125126

126127
builder.activate_block(false)
127-
# Store return value via caller-provided pointer instead of raising
128-
# an exception. This fast path can only be used when the caller is a
129-
# native function.
128+
# The fast path is to store return value via caller-provided pointer
129+
# instead of raising an exception. This can only be used when the
130+
# caller is a native function.
130131
builder.add(SetMem(object_rprimitive, stop_iter_reg, value))
131132
builder.add(Return(Integer(0, object_rprimitive)))
132133

mypyc/irbuild/statement.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
get_exc_info_op,
104104
get_exc_value_op,
105105
keep_propagating_op,
106+
propagate_if_error_op,
106107
raise_exception_op,
107108
reraise_exception_op,
108109
restore_exc_info_op,
@@ -965,7 +966,8 @@ def emit_yield_from_or_await(
965966
obj = builder.read(iter_reg)
966967
nn = builder.none_object()
967968
stop_iter_val = Register(object_rprimitive)
968-
builder.assign(stop_iter_val, Integer(0, object_rprimitive), line)
969+
err = builder.add(LoadErrorValue(object_rprimitive, undefines=True))
970+
builder.assign(stop_iter_val, err, line)
969971
ptr = builder.add(LoadAddress(object_pointer_rprimitive, stop_iter_val))
970972
m = MethodCall(obj, helper_method, [nn, nn, nn, nn, ptr], line)
971973
# Generators have custom error handling, so disable normal error handling.
@@ -979,6 +981,7 @@ def emit_yield_from_or_await(
979981

980982
builder.activate_block(stop_block)
981983
if fast_path:
984+
builder.primitive_op(propagate_if_error_op, [stop_iter_val], line)
982985
builder.assign(result, stop_iter_val, line)
983986
else:
984987
# Try extracting a return value from a StopIteration and return it.

mypyc/lower/misc_ops.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

3-
from mypyc.ir.ops import GetElementPtr, LoadMem, Value
4-
from mypyc.ir.rtypes import PyVarObject, c_pyssize_t_rprimitive
3+
from mypyc.ir.ops import ComparisonOp, GetElementPtr, Integer, LoadMem, Value
4+
from mypyc.ir.rtypes import PyVarObject, c_pyssize_t_rprimitive, object_rprimitive
55
from mypyc.irbuild.ll_builder import LowLevelIRBuilder
66
from mypyc.lower.registry import lower_primitive_op
77

@@ -10,3 +10,8 @@
1010
def var_object_size(builder: LowLevelIRBuilder, args: list[Value], line: int) -> Value:
1111
elem_address = builder.add(GetElementPtr(args[0], PyVarObject, "ob_size"))
1212
return builder.add(LoadMem(c_pyssize_t_rprimitive, elem_address))
13+
14+
15+
@lower_primitive_op("propagate_if_error")
16+
def propagate_if_error_op(builder: LowLevelIRBuilder, args: list[Value], line: int) -> Value:
17+
return builder.add(ComparisonOp(args[0], Integer(0, object_rprimitive), ComparisonOp.NEQ))

mypyc/primitives/exc_ops.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from mypyc.ir.ops import ERR_ALWAYS, ERR_FALSE, ERR_NEVER
66
from mypyc.ir.rtypes import bit_rprimitive, exc_rtuple, object_rprimitive, void_rtype
7-
from mypyc.primitives.registry import custom_op
7+
from mypyc.primitives.registry import custom_op, custom_primitive_op
88

99
# If the argument is a class, raise an instance of the class. Otherwise, assume
1010
# that the argument is an exception object, and raise it.
@@ -62,6 +62,16 @@
6262
error_kind=ERR_FALSE,
6363
)
6464

65+
# If argument is NULL, propagate currently raised exception (in this case
66+
# an exception must have been raised). If this can be used, it's faster
67+
# than using PyErr_Occurred().
68+
propagate_if_error_op = custom_primitive_op(
69+
"propagate_if_error",
70+
arg_types=[object_rprimitive],
71+
return_type=bit_rprimitive,
72+
error_kind=ERR_FALSE,
73+
)
74+
6575
# Catches a propagating exception and makes it the "currently
6676
# handled exception" (by sticking it into sys.exc_info()). Returns the
6777
# exception that was previously being handled, which must be restored

0 commit comments

Comments
 (0)