Skip to content

Commit edd491f

Browse files
authored
perf: return from is_subtype early (#19400)
Our equality implementation is conservative: if two types compare equal, we know for sure they do indeed refer to the same type, and any type is subtype of itself. This saved 0.9% in my local benchmark run.
1 parent 02a472a commit edd491f

File tree

5 files changed

+14
-6
lines changed

5 files changed

+14
-6
lines changed

misc/perf_compare.py

100644100755
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#! /usr/bin/env python
2+
13
"""Compare performance of mypyc-compiled mypy between one or more commits/branches.
24
35
Simple usage:

mypy/subtypes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ def is_subtype(
145145
between the type arguments (e.g., A and B), taking the variance of the
146146
type var into account.
147147
"""
148+
if left == right:
149+
return True
148150
if subtype_context is None:
149151
subtype_context = SubtypeContext(
150152
ignore_type_params=ignore_type_params,
@@ -206,6 +208,8 @@ def is_proper_subtype(
206208
(this is useful for runtime isinstance() checks). If keep_erased_types is True,
207209
do not consider ErasedType a subtype of all types (used by type inference against unions).
208210
"""
211+
if left == right:
212+
return True
209213
if subtype_context is None:
210214
subtype_context = SubtypeContext(
211215
ignore_promotions=ignore_promotions,

mypy/types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,8 @@ def __eq__(self, other: object) -> bool:
22722272
and self.name == other.name
22732273
and self.is_type_obj() == other.is_type_obj()
22742274
and self.is_ellipsis_args == other.is_ellipsis_args
2275+
and self.type_guard == other.type_guard
2276+
and self.type_is == other.type_is
22752277
and self.fallback == other.fallback
22762278
)
22772279
else:

test-data/unit/check-generics.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,8 +2929,8 @@ def mix(fs: List[Callable[[S], T]]) -> Callable[[S], List[T]]:
29292929
def id(__x: U) -> U:
29302930
...
29312931
fs = [id, id, id]
2932-
reveal_type(mix(fs)) # N: Revealed type is "def [S] (S`11) -> builtins.list[S`11]"
2933-
reveal_type(mix([id, id, id])) # N: Revealed type is "def [S] (S`13) -> builtins.list[S`13]"
2932+
reveal_type(mix(fs)) # N: Revealed type is "def [S] (S`7) -> builtins.list[S`7]"
2933+
reveal_type(mix([id, id, id])) # N: Revealed type is "def [S] (S`9) -> builtins.list[S`9]"
29342934
[builtins fixtures/list.pyi]
29352935

29362936
[case testInferenceAgainstGenericCurry]

test-data/unit/check-parameter-specification.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -921,8 +921,8 @@ class A:
921921
def func(self, action: Callable[_P, _R], *args: _P.args, **kwargs: _P.kwargs) -> _R:
922922
...
923923

924-
reveal_type(A.func) # N: Revealed type is "def [_P, _R] (self: __main__.A, action: def (*_P.args, **_P.kwargs) -> _R`6, *_P.args, **_P.kwargs) -> _R`6"
925-
reveal_type(A().func) # N: Revealed type is "def [_P, _R] (action: def (*_P.args, **_P.kwargs) -> _R`10, *_P.args, **_P.kwargs) -> _R`10"
924+
reveal_type(A.func) # N: Revealed type is "def [_P, _R] (self: __main__.A, action: def (*_P.args, **_P.kwargs) -> _R`4, *_P.args, **_P.kwargs) -> _R`4"
925+
reveal_type(A().func) # N: Revealed type is "def [_P, _R] (action: def (*_P.args, **_P.kwargs) -> _R`8, *_P.args, **_P.kwargs) -> _R`8"
926926

927927
def f(x: int) -> int:
928928
...
@@ -953,8 +953,8 @@ class A:
953953
def func(self, action: Job[_P, None]) -> Job[_P, None]:
954954
...
955955

956-
reveal_type(A.func) # N: Revealed type is "def [_P] (self: __main__.A, action: __main__.Job[_P`4, None]) -> __main__.Job[_P`4, None]"
957-
reveal_type(A().func) # N: Revealed type is "def [_P] (action: __main__.Job[_P`6, None]) -> __main__.Job[_P`6, None]"
956+
reveal_type(A.func) # N: Revealed type is "def [_P] (self: __main__.A, action: __main__.Job[_P`3, None]) -> __main__.Job[_P`3, None]"
957+
reveal_type(A().func) # N: Revealed type is "def [_P] (action: __main__.Job[_P`5, None]) -> __main__.Job[_P`5, None]"
958958
reveal_type(A().func(Job(lambda x: x))) # N: Revealed type is "__main__.Job[[x: Any], None]"
959959

960960
def f(x: int, y: int) -> None: ...

0 commit comments

Comments
 (0)