Skip to content

Commit 3703273

Browse files
[mypyc] fix: Final load in unreachable branches (#20617)
- avoid crashing when loading Final values in unreachable branches by falling back to the declared type - add an irbuild-unreachable regression test for Final name loads Fixes mypyc/mypyc#1180
1 parent b11d314 commit 3703273

2 files changed

Lines changed: 45 additions & 8 deletions

File tree

mypyc/irbuild/expression.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,15 @@
4949
UnaryExpr,
5050
Var,
5151
)
52-
from mypy.types import Instance, ProperType, TupleType, TypeType, get_proper_type
52+
from mypy.types import (
53+
AnyType,
54+
Instance,
55+
ProperType,
56+
TupleType,
57+
TypeOfAny,
58+
TypeType,
59+
get_proper_type,
60+
)
5361
from mypyc.common import MAX_SHORT_INT
5462
from mypyc.ir.class_ir import ClassIR
5563
from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD
@@ -147,13 +155,11 @@ def transform_name_expr(builder: IRBuilder, expr: NameExpr) -> Value:
147155
return math_literal
148156

149157
if isinstance(expr.node, Var) and expr.node.is_final:
158+
final_type = builder.types.get(expr) or expr.node.type
159+
if final_type is None:
160+
final_type = AnyType(TypeOfAny.special_form)
150161
value = builder.emit_load_final(
151-
expr.node,
152-
fullname,
153-
expr.name,
154-
builder.is_native_ref_expr(expr),
155-
builder.types[expr],
156-
expr.line,
162+
expr.node, fullname, expr.name, builder.is_native_ref_expr(expr), final_type, expr.line
157163
)
158164
if value is not None:
159165
return value
@@ -208,8 +214,11 @@ def transform_member_expr(builder: IRBuilder, expr: MemberExpr) -> Value:
208214
final = builder.get_final_ref(expr)
209215
if final is not None:
210216
fullname, final_var, native = final
217+
final_type = builder.types.get(expr) or final_var.type
218+
if final_type is None:
219+
final_type = AnyType(TypeOfAny.special_form)
211220
value = builder.emit_load_final(
212-
final_var, fullname, final_var.name, native, builder.types[expr], expr.line
221+
final_var, fullname, final_var.name, native, final_type, expr.line
213222
)
214223
if value is not None:
215224
return value

mypyc/test-data/irbuild-unreachable.test

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,34 @@ L3:
6868
y = r6
6969
return 1
7070

71+
[case testUnreachableFinalNameExpr]
72+
from typing import Final
73+
74+
ZERO: Final = 0
75+
76+
def f(x: int) -> int:
77+
if x is None:
78+
return ZERO
79+
return ZERO
80+
[out]
81+
def f(x):
82+
x :: int
83+
r0, r1 :: object
84+
r2 :: bit
85+
r3 :: object
86+
r4 :: int
87+
L0:
88+
r0 = load_address _Py_NoneStruct
89+
r1 = box(int, x)
90+
r2 = r1 == r0
91+
if r2 goto L1 else goto L2 :: bool
92+
L1:
93+
r3 = object 0
94+
r4 = unbox(int, r3)
95+
return r4
96+
L2:
97+
return 0
98+
7199
[case testUnreachableStatementAfterReturn]
72100
def f(x: bool) -> int:
73101
if x:

0 commit comments

Comments
 (0)