Skip to content

Commit d503edf

Browse files
authored
[mypyc] Raise NameError on undefined names (#19395)
Fixes mypyc/mypyc#879 Changed the type of exception that is raised on undefined names from `RuntimeError` to `NameError`. Moved the runtime error that refers to unexpected execution of unreachable code to `shortcircuit_expr` to keep existing behavior and generate the exception in blocks that are unreachable due to short-circuiting. In the future this could probably be optimized to not generate any code at all and just constant-fold the boolean expression.
1 parent f9fe331 commit d503edf

File tree

4 files changed

+32
-20
lines changed

4 files changed

+32
-20
lines changed

mypyc/irbuild/builder.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,12 +1141,20 @@ def call_refexpr_with_args(
11411141
)
11421142

11431143
def shortcircuit_expr(self, expr: OpExpr) -> Value:
1144+
def handle_right() -> Value:
1145+
if expr.right_unreachable:
1146+
self.builder.add(
1147+
RaiseStandardError(
1148+
RaiseStandardError.RUNTIME_ERROR,
1149+
"mypyc internal error: should be unreachable",
1150+
expr.right.line,
1151+
)
1152+
)
1153+
return self.builder.none()
1154+
return self.accept(expr.right)
1155+
11441156
return self.builder.shortcircuit_helper(
1145-
expr.op,
1146-
self.node_type(expr),
1147-
lambda: self.accept(expr.left),
1148-
lambda: self.accept(expr.right),
1149-
expr.line,
1157+
expr.op, self.node_type(expr), lambda: self.accept(expr.left), handle_right, expr.line
11501158
)
11511159

11521160
# Basic helpers

mypyc/irbuild/expression.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,7 @@ def transform_name_expr(builder: IRBuilder, expr: NameExpr) -> Value:
117117
if expr.node is None:
118118
builder.add(
119119
RaiseStandardError(
120-
RaiseStandardError.RUNTIME_ERROR,
121-
"mypyc internal error: should be unreachable",
122-
expr.line,
120+
RaiseStandardError.NAME_ERROR, f'name "{expr.name}" is not defined', expr.line
123121
)
124122
)
125123
return builder.none()

mypyc/test-data/irbuild-basic.test

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3556,3 +3556,18 @@ L3:
35563556
s = arg
35573557
r3 = CPyObject_Size(s)
35583558
return r3
3559+
3560+
[case testUndefinedFunction]
3561+
def f():
3562+
non_existent_function()
3563+
3564+
[out]
3565+
def f():
3566+
r0 :: bool
3567+
r1, r2, r3 :: object
3568+
L0:
3569+
r0 = raise NameError('name "non_existent_function" is not defined')
3570+
r1 = box(None, 1)
3571+
r2 = PyObject_Vectorcall(r1, 0, 0, 0)
3572+
r3 = box(None, 1)
3573+
return r3

mypyc/test-data/irbuild-unreachable.test

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@ def f():
1717
r8, r9, r10 :: bit
1818
r11, r12 :: bool
1919
r13 :: object
20-
r14 :: str
21-
r15 :: object
22-
r16 :: tuple[int, int]
23-
r17, r18 :: object
24-
r19, y :: bool
20+
r14, y :: bool
2521
L0:
2622
r0 = sys :: module
2723
r1 = 'platform'
@@ -46,13 +42,8 @@ L4:
4642
L5:
4743
r12 = raise RuntimeError('mypyc internal error: should be unreachable')
4844
r13 = box(None, 1)
49-
r14 = 'version_info'
50-
r15 = CPyObject_GetAttr(r13, r14)
51-
r16 = (6, 10)
52-
r17 = box(tuple[int, int], r16)
53-
r18 = PyObject_RichCompare(r15, r17, 4)
54-
r19 = unbox(bool, r18)
55-
r11 = r19
45+
r14 = unbox(bool, r13)
46+
r11 = r14
5647
L6:
5748
y = r11
5849
return 1

0 commit comments

Comments
 (0)