Skip to content

Commit 5d08c47

Browse files
JukkaLilevkivskyi
authored andcommitted
Fix daemon crashes related to ParamSpec and TypeVarTuple (#13381)
* Fix daemon crashes related to ParamSpec and TypeVarTuple Fix daemon crash when using fine-grained caching and ParamSpec, with traceback like this (when using a compiled mypy): ``` Traceback (most recent call last): File "mypy/dmypy_server.py", line 230, in serve File "mypy/dmypy_server.py", line 273, in run_command File "mypy/dmypy_server.py", line 372, in cmd_recheck File "mypy/dmypy_server.py", line 529, in fine_grained_increment File "mypy/server/update.py", line 245, in update File "mypy/server/update.py", line 328, in update_one File "mypy/server/update.py", line 387, in update_module File "mypy/server/astdiff.py", line 158, in snapshot_symbol_table File "mypy/server/astdiff.py", line 236, in snapshot_type File "mypy/types.py", line 1173, in accept File "mypy/server/astdiff.py", line 300, in visit_instance File "mypy/nodes.py", line 2764, in fullname AttributeError: attribute 'TypeInfo' of '_fullname' undefined ``` Also fix TypeVarTuple crashes when using daemon. Co-authored-by: Ivan Levkivskyi <[email protected]>
1 parent 35bc1a2 commit 5d08c47

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

mypy/fixup.py

+8
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
FuncDef,
1414
MypyFile,
1515
OverloadedFuncDef,
16+
ParamSpecExpr,
1617
SymbolTable,
1718
TypeAlias,
1819
TypeInfo,
1920
TypeVarExpr,
21+
TypeVarTupleExpr,
2022
Var,
2123
)
2224
from mypy.types import (
@@ -164,6 +166,12 @@ def visit_type_var_expr(self, tv: TypeVarExpr) -> None:
164166
value.accept(self.type_fixer)
165167
tv.upper_bound.accept(self.type_fixer)
166168

169+
def visit_paramspec_expr(self, p: ParamSpecExpr) -> None:
170+
p.upper_bound.accept(self.type_fixer)
171+
172+
def visit_type_var_tuple_expr(self, tv: TypeVarTupleExpr) -> None:
173+
tv.upper_bound.accept(self.type_fixer)
174+
167175
def visit_var(self, v: Var) -> None:
168176
if self.current_info is not None:
169177
v.info = self.current_info

mypy/server/astdiff.py

+3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method'
6868
TypeAlias,
6969
TypeInfo,
7070
TypeVarExpr,
71+
TypeVarTupleExpr,
7172
Var,
7273
)
7374
from mypy.types import (
@@ -189,6 +190,8 @@ def snapshot_symbol_table(name_prefix: str, table: SymbolTable) -> dict[str, Sna
189190
)
190191
elif isinstance(node, ParamSpecExpr):
191192
result[name] = ("ParamSpec", node.variance, snapshot_type(node.upper_bound))
193+
elif isinstance(node, TypeVarTupleExpr):
194+
result[name] = ("TypeVarTuple", node.variance, snapshot_type(node.upper_bound))
192195
else:
193196
assert symbol.kind != UNBOUND_IMPORTED
194197
if node and get_prefix(node.fullname) != name_prefix:

mypy/test/testfinegrained.py

+1
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ def get_options(self, source: str, testcase: DataDrivenTestCase, build_cache: bo
151151
options.use_fine_grained_cache = self.use_cache and not build_cache
152152
options.cache_fine_grained = self.use_cache
153153
options.local_partial_types = True
154+
options.enable_incomplete_features = True
154155
if re.search("flags:.*--follow-imports", source) is None:
155156
# Override the default for follow_imports
156157
options.follow_imports = "error"

test-data/unit/fine-grained.test

+83
Original file line numberDiff line numberDiff line change
@@ -9819,6 +9819,89 @@ x: str
98199819
[out]
98209820
==
98219821

9822+
[case testParamSpecCached]
9823+
import a
9824+
9825+
[file a.py]
9826+
import b
9827+
9828+
def f(x: int) -> str: return 'x'
9829+
9830+
b.foo(f)
9831+
9832+
[file a.py.2]
9833+
import b
9834+
9835+
def f(x: int) -> str: return 'x'
9836+
9837+
reveal_type(b.foo(f))
9838+
9839+
[file b.py]
9840+
from typing import TypeVar, Callable, Union
9841+
from typing_extensions import ParamSpec
9842+
9843+
P = ParamSpec("P")
9844+
T = TypeVar("T")
9845+
9846+
def foo(f: Callable[P, T]) -> Callable[P, Union[T, None]]:
9847+
return f
9848+
9849+
[file b.py.2]
9850+
from typing import TypeVar, Callable, Union
9851+
from typing_extensions import ParamSpec
9852+
9853+
P = ParamSpec("P")
9854+
T = TypeVar("T")
9855+
9856+
def foo(f: Callable[P, T]) -> Callable[P, Union[T, None]]:
9857+
return f
9858+
9859+
x = 0 # Arbitrary change to trigger reprocessing
9860+
9861+
[builtins fixtures/dict.pyi]
9862+
[out]
9863+
==
9864+
a.py:5: note: Revealed type is "def (x: builtins.int) -> builtins.str"
9865+
9866+
[case testTypeVarTupleCached]
9867+
import a
9868+
9869+
[file a.py]
9870+
import b
9871+
9872+
def f(x: int) -> str: return 'x'
9873+
9874+
b.foo((1, 'x'))
9875+
9876+
[file a.py.2]
9877+
import b
9878+
9879+
reveal_type(b.foo((1, 'x')))
9880+
9881+
[file b.py]
9882+
from typing import Tuple
9883+
from typing_extensions import TypeVarTuple, Unpack
9884+
9885+
Ts = TypeVarTuple("Ts")
9886+
9887+
def foo(t: Tuple[Unpack[Ts]]) -> Tuple[Unpack[Ts]]:
9888+
return t
9889+
9890+
[file b.py.2]
9891+
from typing import Tuple
9892+
from typing_extensions import TypeVarTuple, Unpack
9893+
9894+
Ts = TypeVarTuple("Ts")
9895+
9896+
def foo(t: Tuple[Unpack[Ts]]) -> Tuple[Unpack[Ts]]:
9897+
return t
9898+
9899+
x = 0 # Arbitrary change to trigger reprocessing
9900+
[builtins fixtures/dict.pyi]
9901+
[out]
9902+
==
9903+
a.py:3: note: Revealed type is "Tuple[Literal[1]?, Literal['x']?]"
9904+
98229905
[case testUnpackKwargsUpdateFine]
98239906
# flags: --enable-incomplete-features
98249907
import m

0 commit comments

Comments
 (0)