Skip to content

[mypyc] feat: optimize f-string building from Final values #19611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
12e0a9d
WIP [mypyc] optimize f-string building
BobTheBuidler Aug 7, 2025
5b44af1
Update specialize.py
BobTheBuidler Aug 7, 2025
fc40c81
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 7, 2025
61970f5
Update specialize.py
BobTheBuidler Aug 7, 2025
c5ebd11
Update specialize.py
BobTheBuidler Aug 11, 2025
8a68800
Update specialize.py
BobTheBuidler Aug 11, 2025
996d852
Update specialize.py
BobTheBuidler Aug 11, 2025
3fe0a63
Update specialize.py
BobTheBuidler Aug 11, 2025
c817b67
Update specialize.py
BobTheBuidler Aug 11, 2025
8636006
Update specialize.py
BobTheBuidler Aug 11, 2025
5cee243
Update specialize.py
BobTheBuidler Aug 11, 2025
8b50424
Update specialize.py
BobTheBuidler Aug 11, 2025
712b10a
Update irbuild-str.test
BobTheBuidler Aug 11, 2025
ad58850
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 11, 2025
a69ea3f
Update format_str_tokenizer.py
BobTheBuidler Aug 11, 2025
5351050
Update format_str_tokenizer.py
BobTheBuidler Aug 11, 2025
5b32541
Update irbuild-str.test
BobTheBuidler Aug 11, 2025
0a03849
Update irbuild-str.test
BobTheBuidler Aug 11, 2025
a68c9f8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 11, 2025
0216858
Update specialize.py
BobTheBuidler Aug 11, 2025
6047b0f
Update irbuild-str.test
BobTheBuidler Aug 11, 2025
7b3ca5b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 11, 2025
ceb0e03
Update irbuild-str.test
BobTheBuidler Aug 11, 2025
ba03d50
Update irbuild-str.test
BobTheBuidler Aug 11, 2025
fc973df
Update irbuild-str.test
BobTheBuidler Aug 11, 2025
029b657
Update irbuild-str.test
BobTheBuidler Aug 11, 2025
8064845
fix ir whitespace
BobTheBuidler Aug 11, 2025
55c4a8d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 11, 2025
e71e215
Merge branch 'master' into patch-3
BobTheBuidler Aug 13, 2025
417fa73
Update specialize.py
BobTheBuidler Aug 13, 2025
aed4c1d
add more tests
BobTheBuidler Aug 13, 2025
1de5018
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2025
212bee8
Update specialize.py
BobTheBuidler Aug 14, 2025
80a97a9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 14, 2025
60c8af0
Merge branch 'master' into patch-3
BobTheBuidler Aug 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions mypyc/irbuild/format_str_tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
)
from mypy.errors import Errors
from mypy.messages import MessageBuilder
from mypy.nodes import Context, Expression
from mypy.nodes import Context, Expression, StrExpr
from mypy.options import Options
from mypyc.ir.ops import Integer, Value
from mypyc.ir.rtypes import (
Expand Down Expand Up @@ -143,7 +143,9 @@ def convert_format_expr_to_str(
for x, format_op in zip(exprs, format_ops):
node_type = builder.node_type(x)
if format_op == FormatOp.STR:
if is_str_rprimitive(node_type):
if is_str_rprimitive(node_type) or isinstance(
x, StrExpr
): # NOTE: why does mypyc think our fake StrExprs are not str rprimitives?
var_str = builder.accept(x)
elif is_int_rprimitive(node_type) or is_short_int_rprimitive(node_type):
var_str = builder.primitive_op(int_to_str_op, [builder.accept(x)], line)
Expand Down
23 changes: 23 additions & 0 deletions mypyc/irbuild/specialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
RefExpr,
StrExpr,
TupleExpr,
Var,
)
from mypy.types import AnyType, TypeOfAny
from mypyc.ir.ops import (
Expand Down Expand Up @@ -710,6 +711,28 @@ def translate_fstring(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Va
format_ops.append(FormatOp.STR)
exprs.append(item.args[0])

for i in range(len(exprs) - 1):

def get_literal_str(expr: Expression) -> str | None:
# NOTE: not sure where I should put this helper, this file? somewhere else?
if isinstance(expr, StrExpr):
return expr.value
elif (
isinstance(expr, RefExpr)
and isinstance(expr.node, Var)
and expr.node.final_value is not None
):
return str(expr.node.final_value)
return None

while (
len(exprs) >= i + 2
and (first := get_literal_str(exprs[i])) is not None
and (second := get_literal_str(exprs[i + 1])) is not None
):
exprs = [*exprs[:i], StrExpr(first + second), *exprs[i + 2 :]]
format_ops = [*format_ops[:i], FormatOp.STR, *format_ops[i + 2 :]]

substitutions = convert_format_expr_to_str(builder, format_ops, exprs, expr.line)
if substitutions is None:
return None
Expand Down
20 changes: 20 additions & 0 deletions mypyc/test-data/irbuild-str.test
Original file line number Diff line number Diff line change
Expand Up @@ -605,3 +605,23 @@ L3:
r6 = r7
L4:
return r6

[case testFStringFromConstants]
from typing import Final
string: Final = "abc"
integer: Final = 123
floating: Final = 3.14
boolean: Final = True

def test(x: str) -> str:
return f"{string}{integer}{floating}{boolean}{x}{boolean}{floating}{integer}{string}{x}{string}{integer}{floating}{boolean}{x}"

[out]
def test(x):
x, r0, r1, r2, r3 :: str
L0:
r0 = 'abc1233.14True'
r1 = 'True3.14123abc'
r2 = 'abc1233.14True'
r3 = CPyStr_Build(6, r0, x, r1, x, r2, x)
return r3
Loading