|
6 | 6 | from collections import defaultdict
|
7 | 7 | from collections.abc import Iterable, Iterator, Mapping, Sequence, Set as AbstractSet
|
8 | 8 | from contextlib import ExitStack, contextmanager
|
9 |
| -from typing import Callable, Final, Generic, NamedTuple, Optional, TypeVar, Union, cast, overload |
| 9 | +from typing import ( |
| 10 | + Callable, |
| 11 | + Final, |
| 12 | + Generic, |
| 13 | + Literal, |
| 14 | + NamedTuple, |
| 15 | + Optional, |
| 16 | + TypeVar, |
| 17 | + Union, |
| 18 | + cast, |
| 19 | + overload, |
| 20 | +) |
10 | 21 | from typing_extensions import TypeAlias as _TypeAlias, TypeGuard
|
11 | 22 |
|
12 | 23 | import mypy.checkexpr
|
@@ -277,6 +288,26 @@ class PartialTypeScope(NamedTuple):
|
277 | 288 | is_local: bool
|
278 | 289 |
|
279 | 290 |
|
| 291 | +class LocalTypeMap: |
| 292 | + """Store inferred types into a temporary type map (returned). |
| 293 | +
|
| 294 | + This can be used to perform type checking "experiments" without |
| 295 | + affecting exported types (which are used by mypyc). |
| 296 | + """ |
| 297 | + |
| 298 | + def __init__(self, chk: TypeChecker) -> None: |
| 299 | + self.chk = chk |
| 300 | + |
| 301 | + def __enter__(self) -> dict[Expression, Type]: |
| 302 | + temp_type_map: dict[Expression, Type] = {} |
| 303 | + self.chk._type_maps.append(temp_type_map) |
| 304 | + return temp_type_map |
| 305 | + |
| 306 | + def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> Literal[False]: |
| 307 | + self.chk._type_maps.pop() |
| 308 | + return False |
| 309 | + |
| 310 | + |
280 | 311 | class TypeChecker(NodeVisitor[None], TypeCheckerSharedApi):
|
281 | 312 | """Mypy type checker.
|
282 | 313 |
|
@@ -402,6 +433,7 @@ def __init__(
|
402 | 433 | self.is_typeshed_stub = tree.is_typeshed_file(options)
|
403 | 434 | self.inferred_attribute_types = None
|
404 | 435 | self.allow_constructor_cache = True
|
| 436 | + self.local_type_map = LocalTypeMap(self) |
405 | 437 |
|
406 | 438 | # If True, process function definitions. If False, don't. This is used
|
407 | 439 | # for processing module top levels in fine-grained incremental mode.
|
@@ -4631,7 +4663,7 @@ def check_simple_assignment(
|
4631 | 4663 | # may cause some perf impact, plus we want to partially preserve
|
4632 | 4664 | # the old behavior. This helps with various practical examples, see
|
4633 | 4665 | # e.g. testOptionalTypeNarrowedByGenericCall.
|
4634 |
| - with self.msg.filter_errors() as local_errors, self.local_type_map() as type_map: |
| 4666 | + with self.msg.filter_errors() as local_errors, self.local_type_map as type_map: |
4635 | 4667 | alt_rvalue_type = self.expr_checker.accept(
|
4636 | 4668 | rvalue, None, always_allow_any=always_allow_any
|
4637 | 4669 | )
|
@@ -7458,18 +7490,6 @@ def lookup_type(self, node: Expression) -> Type:
|
7458 | 7490 | def store_types(self, d: dict[Expression, Type]) -> None:
|
7459 | 7491 | self._type_maps[-1].update(d)
|
7460 | 7492 |
|
7461 |
| - @contextmanager |
7462 |
| - def local_type_map(self) -> Iterator[dict[Expression, Type]]: |
7463 |
| - """Store inferred types into a temporary type map (returned). |
7464 |
| -
|
7465 |
| - This can be used to perform type checking "experiments" without |
7466 |
| - affecting exported types (which are used by mypyc). |
7467 |
| - """ |
7468 |
| - temp_type_map: dict[Expression, Type] = {} |
7469 |
| - self._type_maps.append(temp_type_map) |
7470 |
| - yield temp_type_map |
7471 |
| - self._type_maps.pop() |
7472 |
| - |
7473 | 7493 | def in_checked_function(self) -> bool:
|
7474 | 7494 | """Should we type-check the current function?
|
7475 | 7495 |
|
|
0 commit comments