Skip to content

Commit fa35c86

Browse files
Merge branch 'master' into constant-fold-namedtuple-fields
2 parents 8784a7c + c71fef0 commit fa35c86

File tree

4 files changed

+36
-79
lines changed

4 files changed

+36
-79
lines changed

mypy/cache.py

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

33
from collections.abc import Sequence
4-
from typing import TYPE_CHECKING, Final
4+
from typing import Final
55

66
from mypy_extensions import u8
7-
8-
try:
9-
from native_internal import (
10-
Buffer as Buffer,
11-
read_bool as read_bool,
12-
read_float as read_float,
13-
read_int as read_int,
14-
read_str as read_str,
15-
read_tag as read_tag,
16-
write_bool as write_bool,
17-
write_float as write_float,
18-
write_int as write_int,
19-
write_str as write_str,
20-
write_tag as write_tag,
21-
)
22-
except ImportError:
23-
# TODO: temporary, remove this after we publish mypy-native on PyPI.
24-
if not TYPE_CHECKING:
25-
26-
class Buffer:
27-
def __init__(self, source: bytes = b"") -> None:
28-
raise NotImplementedError
29-
30-
def getvalue(self) -> bytes:
31-
raise NotImplementedError
32-
33-
def read_int(data: Buffer) -> int:
34-
raise NotImplementedError
35-
36-
def write_int(data: Buffer, value: int) -> None:
37-
raise NotImplementedError
38-
39-
def read_tag(data: Buffer) -> u8:
40-
raise NotImplementedError
41-
42-
def write_tag(data: Buffer, value: u8) -> None:
43-
raise NotImplementedError
44-
45-
def read_str(data: Buffer) -> str:
46-
raise NotImplementedError
47-
48-
def write_str(data: Buffer, value: str) -> None:
49-
raise NotImplementedError
50-
51-
def read_bool(data: Buffer) -> bool:
52-
raise NotImplementedError
53-
54-
def write_bool(data: Buffer, value: bool) -> None:
55-
raise NotImplementedError
56-
57-
def read_float(data: Buffer) -> float:
58-
raise NotImplementedError
59-
60-
def write_float(data: Buffer, value: float) -> None:
61-
raise NotImplementedError
62-
7+
from native_internal import (
8+
Buffer as Buffer,
9+
read_bool as read_bool,
10+
read_float as read_float,
11+
read_int as read_int,
12+
read_str as read_str,
13+
read_tag as read_tag,
14+
write_bool as write_bool,
15+
write_float as write_float,
16+
write_int as write_int,
17+
write_str as write_str,
18+
write_tag as write_tag,
19+
)
6320

6421
# Always use this type alias to refer to type tags.
6522
Tag = u8

mypy/checkexpr.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from mypy.checker_shared import ExpressionCheckerSharedApi
1919
from mypy.checkmember import analyze_member_access, has_operator
2020
from mypy.checkstrformat import StringFormatterChecker
21+
from mypy.constant_fold import constant_fold_expr
2122
from mypy.erasetype import erase_type, remove_instance_last_known_values, replace_meta_vars
2223
from mypy.errors import ErrorInfo, ErrorWatcher, report_internal_error
2324
from mypy.expandtype import (
@@ -656,11 +657,12 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) ->
656657
return ret_type
657658

658659
def check_str_format_call(self, e: CallExpr) -> None:
659-
"""More precise type checking for str.format() calls on literals."""
660+
"""More precise type checking for str.format() calls on literals and folded constants."""
660661
assert isinstance(e.callee, MemberExpr)
661662
format_value = None
662-
if isinstance(e.callee.expr, StrExpr):
663-
format_value = e.callee.expr.value
663+
folded_callee_expr = constant_fold_expr(e.callee.expr, "<unused>")
664+
if isinstance(folded_callee_expr, str):
665+
format_value = folded_callee_expr
664666
elif self.chk.has_type(e.callee.expr):
665667
typ = get_proper_type(self.chk.lookup_type(e.callee.expr))
666668
if (

mypyc/irbuild/expression.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value:
558558
# Special case some int ops to allow borrowing operands.
559559
if is_int_rprimitive(ltype) and is_int_rprimitive(rtype):
560560
if expr.op == "//":
561-
expr = try_optimize_int_floor_divide(expr)
561+
expr = try_optimize_int_floor_divide(builder, expr)
562562
if expr.op in int_borrow_friendly_op:
563563
borrow_left = is_borrow_friendly_expr(builder, expr.right)
564564
borrow_right = True
@@ -571,11 +571,11 @@ def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value:
571571
return builder.binary_op(left, right, expr.op, expr.line)
572572

573573

574-
def try_optimize_int_floor_divide(expr: OpExpr) -> OpExpr:
574+
def try_optimize_int_floor_divide(builder: IRBuilder, expr: OpExpr) -> OpExpr:
575575
"""Replace // with a power of two with a right shift, if possible."""
576-
if not isinstance(expr.right, IntExpr):
576+
divisor = constant_fold_expr(builder, expr.right)
577+
if not isinstance(divisor, int):
577578
return expr
578-
divisor = expr.right.value
579579
shift = divisor.bit_length() - 1
580580
if 0 < shift < 28 and divisor == (1 << shift):
581581
return OpExpr(">>", expr.left, IntExpr(shift))

mypyc/irbuild/specialize.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
uint8_rprimitive,
7979
)
8080
from mypyc.irbuild.builder import IRBuilder
81+
from mypyc.irbuild.constant_fold import constant_fold_expr
8182
from mypyc.irbuild.for_helpers import (
8283
comprehension_helper,
8384
sequence_from_generator_preallocate_helper,
@@ -716,21 +717,18 @@ def translate_dict_setdefault(builder: IRBuilder, expr: CallExpr, callee: RefExp
716717

717718
@specialize_function("format", str_rprimitive)
718719
def translate_str_format(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Value | None:
719-
if (
720-
isinstance(callee, MemberExpr)
721-
and isinstance(callee.expr, StrExpr)
722-
and expr.arg_kinds.count(ARG_POS) == len(expr.arg_kinds)
723-
):
724-
format_str = callee.expr.value
725-
tokens = tokenizer_format_call(format_str)
726-
if tokens is None:
727-
return None
728-
literals, format_ops = tokens
729-
# Convert variables to strings
730-
substitutions = convert_format_expr_to_str(builder, format_ops, expr.args, expr.line)
731-
if substitutions is None:
732-
return None
733-
return join_formatted_strings(builder, literals, substitutions, expr.line)
720+
if isinstance(callee, MemberExpr):
721+
folded_callee = constant_fold_expr(builder, callee.expr)
722+
if isinstance(folded_callee, str) and expr.arg_kinds.count(ARG_POS) == len(expr.arg_kinds):
723+
tokens = tokenizer_format_call(folded_callee)
724+
if tokens is None:
725+
return None
726+
literals, format_ops = tokens
727+
# Convert variables to strings
728+
substitutions = convert_format_expr_to_str(builder, format_ops, expr.args, expr.line)
729+
if substitutions is None:
730+
return None
731+
return join_formatted_strings(builder, literals, substitutions, expr.line)
734732
return None
735733

736734

0 commit comments

Comments
 (0)