Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent crash on generic NamedTuple with unresolved typevar bound #18585

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -8485,6 +8485,11 @@ def visit_type_var(self, t: TypeVarType) -> bool:
# multi-step type inference.
return t.id.is_meta_var()

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


class SetNothingToAny(TypeTranslator):
"""Replace all ambiguous Uninhabited types with Any (to avoid spurious extra errors)."""
Expand Down
4 changes: 2 additions & 2 deletions mypy/type_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ def visit_callable_type(self, t: CallableType, /) -> T:
return self.query_types(t.arg_types + [t.ret_type])

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

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

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

def visit_typeddict_type(self, t: TypedDictType, /) -> bool:
return self.query_types(list(t.items.values()))
Expand Down
19 changes: 19 additions & 0 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -6829,3 +6829,22 @@ reveal_type(a.f)
tmp/b.py:4: note: Revealed type is "builtins.int"
tmp/b.py:5: error: Incompatible types in assignment (expression has type "int", variable has type "str")
tmp/b.py:6: note: Revealed type is "builtins.int"

[case testSerializeDeferredGenericNamedTuple]
import pkg
[file pkg/__init__.py]
from .lib import NT
[file pkg/lib.py]
from typing import Generic, NamedTuple, TypeVar
from pkg import does_not_exist # type: ignore
from pkg.missing import also_missing # type: ignore

T = TypeVar("T", bound=does_not_exist)
class NT(NamedTuple, Generic[T]):
values: also_missing[T]
[file pkg/__init__.py.2]
# touch
from .lib import NT
[builtins fixtures/tuple.pyi]
[out]
[out2]
8 changes: 8 additions & 0 deletions test-data/unit/check-inference.test
Original file line number Diff line number Diff line change
Expand Up @@ -3886,3 +3886,11 @@ def a4(x: List[str], y: List[Never]) -> None:
reveal_type(z2) # N: Revealed type is "builtins.list[builtins.object]"
z1[1].append("asdf") # E: "object" has no attribute "append"
[builtins fixtures/dict.pyi]

[case testTupleJoinFallbackInference]
foo = [
(1, ("a", "b")),
(2, []),
]
reveal_type(foo) # N: Revealed type is "builtins.list[Tuple[builtins.int, typing.Sequence[builtins.str]]]"
[builtins fixtures/tuple.pyi]