Skip to content

Commit 5a78607

Browse files
Another two micro-optimizations (#19633)
Here are two things: * Make `FormalArgument` a native class. We create huge amount of these (as callable subtyping is one of the most common subtype checks), and named tuples creation is significantly slower than native classes. * Do not call `re.match()` in a code path of `format_type()`. This is relatively slow (as it is a `py_call()`) and it is called in almost every error message. This creates problems for code with many third-party dependencies where these errors are ignored anyway. FWIW in total these give ~0.5% together (I didn't measure individually, but I guess the most benefit for self-check is from the first one). --------- Co-authored-by: Ali Hamdan <[email protected]>
1 parent 6d0ce5e commit 5a78607

File tree

3 files changed

+24
-24
lines changed

3 files changed

+24
-24
lines changed

mypy/messages.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,13 +2432,13 @@ def format_long_tuple_type(self, typ: TupleType) -> str:
24322432
"""Format very long tuple type using an ellipsis notation"""
24332433
item_cnt = len(typ.items)
24342434
if item_cnt > MAX_TUPLE_ITEMS:
2435-
return "tuple[{}, {}, ... <{} more items>]".format(
2435+
return '"tuple[{}, {}, ... <{} more items>]"'.format(
24362436
format_type_bare(typ.items[0], self.options),
24372437
format_type_bare(typ.items[1], self.options),
24382438
str(item_cnt - 2),
24392439
)
24402440
else:
2441-
return format_type_bare(typ, self.options)
2441+
return format_type(typ, self.options)
24422442

24432443
def generate_incompatible_tuple_error(
24442444
self,
@@ -2517,15 +2517,12 @@ def iteration_dependent_errors(self, iter_errors: IterationDependentErrors) -> N
25172517

25182518
def quote_type_string(type_string: str) -> str:
25192519
"""Quotes a type representation for use in messages."""
2520-
no_quote_regex = r"^<(tuple|union): \d+ items>$"
25212520
if (
25222521
type_string in ["Module", "overloaded function", "<deleted>"]
25232522
or type_string.startswith("Module ")
2524-
or re.match(no_quote_regex, type_string) is not None
25252523
or type_string.endswith("?")
25262524
):
2527-
# Messages are easier to read if these aren't quoted. We use a
2528-
# regex to match strings with variable contents.
2525+
# These messages are easier to read if these aren't quoted.
25292526
return type_string
25302527
return f'"{type_string}"'
25312528

mypy/types.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,7 @@
55
import sys
66
from abc import abstractmethod
77
from collections.abc import Iterable, Sequence
8-
from typing import (
9-
TYPE_CHECKING,
10-
Any,
11-
ClassVar,
12-
Final,
13-
NamedTuple,
14-
NewType,
15-
TypeVar,
16-
Union,
17-
cast,
18-
overload,
19-
)
8+
from typing import TYPE_CHECKING, Any, ClassVar, Final, NewType, TypeVar, Union, cast, overload
209
from typing_extensions import Self, TypeAlias as _TypeAlias, TypeGuard
2110

2211
import mypy.nodes
@@ -1607,11 +1596,25 @@ def bound(self) -> bool:
16071596
return bool(self.items) and self.items[0].is_bound
16081597

16091598

1610-
class FormalArgument(NamedTuple):
1611-
name: str | None
1612-
pos: int | None
1613-
typ: Type
1614-
required: bool
1599+
class FormalArgument:
1600+
def __init__(self, name: str | None, pos: int | None, typ: Type, required: bool) -> None:
1601+
self.name = name
1602+
self.pos = pos
1603+
self.typ = typ
1604+
self.required = required
1605+
1606+
def __eq__(self, other: object) -> bool:
1607+
if not isinstance(other, FormalArgument):
1608+
return NotImplemented
1609+
return (
1610+
self.name == other.name
1611+
and self.pos == other.pos
1612+
and self.typ == other.typ
1613+
and self.required == other.required
1614+
)
1615+
1616+
def __hash__(self) -> int:
1617+
return hash((self.name, self.pos, self.typ, self.required))
16151618

16161619

16171620
class Parameters(ProperType):

test-data/unit/check-tuples.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1612,7 +1612,7 @@ t4: Tuple[int, int, int, int, int, int, int, int, int, int, int, int] = (1, 2, 3
16121612
t5: Tuple[int, int] = (1, 2, "s", 4) # E: Incompatible types in assignment (expression has type "tuple[int, int, str, int]", variable has type "tuple[int, int]")
16131613

16141614
# long initializer assignment with mismatched pairs
1615-
t6: Tuple[int, int, int, int, int, int, int, int, int, int, int, int] = (1, 2, 3, 4, 5, 6, 7, 8, "str", "str", "str", "str", 1, 1, 1, 1, 1) # E: Incompatible types in assignment (expression has type tuple[int, int, ... <15 more items>], variable has type tuple[int, int, ... <10 more items>])
1615+
t6: Tuple[int, int, int, int, int, int, int, int, int, int, int, int] = (1, 2, 3, 4, 5, 6, 7, 8, "str", "str", "str", "str", 1, 1, 1, 1, 1) # E: Incompatible types in assignment (expression has type "tuple[int, int, ... <15 more items>]", variable has type "tuple[int, int, ... <10 more items>]")
16161616

16171617
[builtins fixtures/tuple.pyi]
16181618

0 commit comments

Comments
 (0)