Skip to content

Commit 237933a

Browse files
Prevent crash on generic NamedTuple with unresolved typevar bound (#18585)
Fixes #18582. Fixes #17396. Supersedes #18351. --------- Co-authored-by: hauntsaninja <[email protected]>
1 parent 02f9a70 commit 237933a

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

mypy/checker.py

+5
Original file line numberDiff line numberDiff line change
@@ -8485,6 +8485,11 @@ def visit_type_var(self, t: TypeVarType) -> bool:
84858485
# multi-step type inference.
84868486
return t.id.is_meta_var()
84878487

8488+
def visit_tuple_type(self, t: TupleType, /) -> bool:
8489+
# Exclude fallback to avoid bogus "need type annotation" errors
8490+
# TODO: Maybe erase plain tuples used as fallback in TupleType constructor?
8491+
return self.query_types(t.items)
8492+
84888493

84898494
class SetNothingToAny(TypeTranslator):
84908495
"""Replace all ambiguous Uninhabited types with Any (to avoid spurious extra errors)."""

mypy/type_visitor.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ def visit_callable_type(self, t: CallableType, /) -> T:
410410
return self.query_types(t.arg_types + [t.ret_type])
411411

412412
def visit_tuple_type(self, t: TupleType, /) -> T:
413-
return self.query_types(t.items)
413+
return self.query_types([t.partial_fallback] + t.items)
414414

415415
def visit_typeddict_type(self, t: TypedDictType, /) -> T:
416416
return self.query_types(t.items.values())
@@ -550,7 +550,7 @@ def visit_callable_type(self, t: CallableType, /) -> bool:
550550
return args and ret
551551

552552
def visit_tuple_type(self, t: TupleType, /) -> bool:
553-
return self.query_types(t.items)
553+
return self.query_types([t.partial_fallback] + t.items)
554554

555555
def visit_typeddict_type(self, t: TypedDictType, /) -> bool:
556556
return self.query_types(list(t.items.values()))

test-data/unit/check-incremental.test

+19
Original file line numberDiff line numberDiff line change
@@ -6829,3 +6829,22 @@ reveal_type(a.f)
68296829
tmp/b.py:4: note: Revealed type is "builtins.int"
68306830
tmp/b.py:5: error: Incompatible types in assignment (expression has type "int", variable has type "str")
68316831
tmp/b.py:6: note: Revealed type is "builtins.int"
6832+
6833+
[case testSerializeDeferredGenericNamedTuple]
6834+
import pkg
6835+
[file pkg/__init__.py]
6836+
from .lib import NT
6837+
[file pkg/lib.py]
6838+
from typing import Generic, NamedTuple, TypeVar
6839+
from pkg import does_not_exist # type: ignore
6840+
from pkg.missing import also_missing # type: ignore
6841+
6842+
T = TypeVar("T", bound=does_not_exist)
6843+
class NT(NamedTuple, Generic[T]):
6844+
values: also_missing[T]
6845+
[file pkg/__init__.py.2]
6846+
# touch
6847+
from .lib import NT
6848+
[builtins fixtures/tuple.pyi]
6849+
[out]
6850+
[out2]

test-data/unit/check-inference.test

+8
Original file line numberDiff line numberDiff line change
@@ -3886,3 +3886,11 @@ def a4(x: List[str], y: List[Never]) -> None:
38863886
reveal_type(z2) # N: Revealed type is "builtins.list[builtins.object]"
38873887
z1[1].append("asdf") # E: "object" has no attribute "append"
38883888
[builtins fixtures/dict.pyi]
3889+
3890+
[case testTupleJoinFallbackInference]
3891+
foo = [
3892+
(1, ("a", "b")),
3893+
(2, []),
3894+
]
3895+
reveal_type(foo) # N: Revealed type is "builtins.list[Tuple[builtins.int, typing.Sequence[builtins.str]]]"
3896+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)