Skip to content

Commit 402c8ff

Browse files
authored
Fix crash on malformed TypedDict in incremental mode (#16115)
Fixes #15557 FWIW I simply copy the logic for handling malformed definitions from named tuples, that seems to be much more robust.
1 parent d77310a commit 402c8ff

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

mypy/semanal_typeddict.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,13 @@ def check_typeddict(
366366
name, items, types, total, tvar_defs, ok = res
367367
if not ok:
368368
# Error. Construct dummy return value.
369-
info = self.build_typeddict_typeinfo("TypedDict", [], [], set(), call.line, None)
369+
if var_name:
370+
name = var_name
371+
if is_func_scope:
372+
name += "@" + str(call.line)
373+
else:
374+
name = var_name = "TypedDict@" + str(call.line)
375+
info = self.build_typeddict_typeinfo(name, [], [], set(), call.line, None)
370376
else:
371377
if var_name is not None and name != var_name:
372378
self.fail(
@@ -395,9 +401,9 @@ def check_typeddict(
395401
name, items, types, required_keys, call.line, existing_info
396402
)
397403
info.line = node.line
398-
# Store generated TypeInfo under both names, see semanal_namedtuple for more details.
399-
if name != var_name or is_func_scope:
400-
self.api.add_symbol_skip_local(name, info)
404+
# Store generated TypeInfo under both names, see semanal_namedtuple for more details.
405+
if name != var_name or is_func_scope:
406+
self.api.add_symbol_skip_local(name, info)
401407
if var_name:
402408
self.api.add_symbol(var_name, info, node)
403409
call.analyzed = TypedDictExpr(info)

test-data/unit/check-incremental.test

+25
Original file line numberDiff line numberDiff line change
@@ -6479,3 +6479,28 @@ from typing_extensions import TypeVarTuple, Unpack
64796479
Ts = TypeVarTuple("Ts")
64806480
class C(Tuple[Unpack[Ts]]): ...
64816481
[builtins fixtures/tuple.pyi]
6482+
6483+
[case testNoIncrementalCrashOnInvalidTypedDict]
6484+
import m
6485+
[file m.py]
6486+
import counts
6487+
[file m.py.2]
6488+
import counts
6489+
# touch
6490+
[file counts.py]
6491+
from typing_extensions import TypedDict
6492+
Counts = TypedDict("Counts", {k: int for k in "abc"}) # type: ignore
6493+
[builtins fixtures/dict.pyi]
6494+
6495+
[case testNoIncrementalCrashOnInvalidTypedDictFunc]
6496+
import m
6497+
[file m.py]
6498+
import counts
6499+
[file m.py.2]
6500+
import counts
6501+
# touch
6502+
[file counts.py]
6503+
from typing_extensions import TypedDict
6504+
def test() -> None:
6505+
Counts = TypedDict("Counts", {k: int for k in "abc"}) # type: ignore
6506+
[builtins fixtures/dict.pyi]

0 commit comments

Comments
 (0)