Skip to content

Commit 0430236

Browse files
[mypyc] extend get_expr_length to try constant_fold_expr [1/4] (#19930)
Among other things, `get_expr_length` currently supports StrExpr, BytesExpr, and string-type Final values. `constant_fold_expr` already has the code to parse values from all of these, so we can use it to deduplicate code in `get_expr_length`. It's able to parse a few more Expressions than our existing implementation, not that any of these are particularly relevant at the moment, and allows get_expr_length to automatically benefit from more relevant future constant-folding enhancements.
1 parent dabcce9 commit 0430236

File tree

2 files changed

+52
-13
lines changed

2 files changed

+52
-13
lines changed

mypyc/irbuild/for_helpers.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
from mypy.nodes import (
1414
ARG_POS,
15-
BytesExpr,
1615
CallExpr,
1716
DictionaryComprehension,
1817
Expression,
@@ -24,10 +23,8 @@
2423
RefExpr,
2524
SetExpr,
2625
StarExpr,
27-
StrExpr,
2826
TupleExpr,
2927
TypeAlias,
30-
Var,
3128
)
3229
from mypy.types import LiteralType, TupleType, get_proper_type, get_proper_types
3330
from mypyc.ir.ops import (
@@ -68,6 +65,7 @@
6865
short_int_rprimitive,
6966
)
7067
from mypyc.irbuild.builder import IRBuilder
68+
from mypyc.irbuild.constant_fold import constant_fold_expr
7169
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
7270
from mypyc.irbuild.targets import AssignmentTarget, AssignmentTargetTuple
7371
from mypyc.primitives.dict_ops import (
@@ -1225,8 +1223,9 @@ def gen_cleanup(self) -> None:
12251223

12261224

12271225
def get_expr_length(builder: IRBuilder, expr: Expression) -> int | None:
1228-
if isinstance(expr, (StrExpr, BytesExpr)):
1229-
return len(expr.value)
1226+
folded = constant_fold_expr(builder, expr)
1227+
if isinstance(folded, (str, bytes)):
1228+
return len(folded)
12301229
elif isinstance(expr, (ListExpr, TupleExpr)):
12311230
# if there are no star expressions, or we know the length of them,
12321231
# we know the length of the expression
@@ -1236,14 +1235,6 @@ def get_expr_length(builder: IRBuilder, expr: Expression) -> int | None:
12361235
return other + sum(stars) # type: ignore [arg-type]
12371236
elif isinstance(expr, StarExpr):
12381237
return get_expr_length(builder, expr.expr)
1239-
elif (
1240-
isinstance(expr, RefExpr)
1241-
and isinstance(expr.node, Var)
1242-
and expr.node.is_final
1243-
and isinstance(expr.node.final_value, str)
1244-
and expr.node.has_explicit_value
1245-
):
1246-
return len(expr.node.final_value)
12471238
# TODO: extend this, passing length of listcomp and genexp should have worthwhile
12481239
# performance boost and can be (sometimes) figured out pretty easily. set and dict
12491240
# comps *can* be done as well but will need special logic to consider the possibility

mypyc/test-data/irbuild-tuple.test

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,54 @@ L4:
434434
a = r1
435435
return 1
436436

437+
[case testTupleBuiltFromConstantFolding]
438+
from typing import Final
439+
440+
c: Final = "c"
441+
442+
def f2(val: str) -> str:
443+
return val + "f2"
444+
445+
def test() -> None:
446+
# `"ab" + c` should constant fold to "abc"
447+
a = tuple(f2(x) for x in "ab" + c)
448+
449+
[out]
450+
def f2(val):
451+
val, r0, r1 :: str
452+
L0:
453+
r0 = 'f2'
454+
r1 = PyUnicode_Concat(val, r0)
455+
return r1
456+
def test():
457+
r0 :: str
458+
r1 :: tuple
459+
r2 :: native_int
460+
r3 :: bit
461+
r4, x, r5 :: str
462+
r6 :: native_int
463+
a :: tuple
464+
L0:
465+
r0 = 'abc'
466+
r1 = PyTuple_New(3)
467+
r2 = 0
468+
goto L2
469+
L1:
470+
r3 = r2 < 3 :: signed
471+
if r3 goto L2 else goto L4 :: bool
472+
L2:
473+
r4 = CPyStr_GetItemUnsafe(r0, r2)
474+
x = r4
475+
r5 = f2(x)
476+
CPySequenceTuple_SetItemUnsafe(r1, r2, r5)
477+
L3:
478+
r6 = r2 + 1
479+
r2 = r6
480+
goto L1
481+
L4:
482+
a = r1
483+
return 1
484+
437485
[case testTupleBuiltFromFinalStr]
438486
from typing import Final
439487

0 commit comments

Comments
 (0)