From 510d717ddf0b8536b07e7805af01cc0d48f3faa6 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 14 Feb 2023 13:49:27 +0000 Subject: [PATCH] Fix generic TypedDict/NamedTuple fixup (#14675) Fixes #14638 TBH I don't remember why do we need to create the "incomplete" type alias (with empty type variables), and set up type variables later. But I didn't want to risk a larger refactoring and just fixed the missing calls surfaced by the issue instead. --- mypy/fixup.py | 4 +++ mypy/nodes.py | 14 +++++++-- test-data/unit/check-incremental.test | 44 +++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/mypy/fixup.py b/mypy/fixup.py index 3593e4faa184..af6d3f3d7b07 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -80,9 +80,13 @@ def visit_type_info(self, info: TypeInfo) -> None: if info.tuple_type: info.tuple_type.accept(self.type_fixer) info.update_tuple_type(info.tuple_type) + if info.special_alias: + info.special_alias.alias_tvars = list(info.defn.type_vars) if info.typeddict_type: info.typeddict_type.accept(self.type_fixer) info.update_typeddict_type(info.typeddict_type) + if info.special_alias: + info.special_alias.alias_tvars = list(info.defn.type_vars) if info.declared_metaclass: info.declared_metaclass.accept(self.type_fixer) if info.metaclass_type: diff --git a/mypy/nodes.py b/mypy/nodes.py index 98976f4fe56a..b1c12cde9981 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -3473,8 +3473,13 @@ def __init__( @classmethod def from_tuple_type(cls, info: TypeInfo) -> TypeAlias: - """Generate an alias to the tuple type described by a given TypeInfo.""" + """Generate an alias to the tuple type described by a given TypeInfo. + + NOTE: this doesn't set type alias type variables (for generic tuple types), + they must be set by the caller (when fully analyzed). + """ assert info.tuple_type + # TODO: is it possible to refactor this to set the correct type vars here? return TypeAlias( info.tuple_type.copy_modified(fallback=mypy.types.Instance(info, info.defn.type_vars)), info.fullname, @@ -3484,8 +3489,13 @@ def from_tuple_type(cls, info: TypeInfo) -> TypeAlias: @classmethod def from_typeddict_type(cls, info: TypeInfo) -> TypeAlias: - """Generate an alias to the TypedDict type described by a given TypeInfo.""" + """Generate an alias to the TypedDict type described by a given TypeInfo. + + NOTE: this doesn't set type alias type variables (for generic TypedDicts), + they must be set by the caller (when fully analyzed). + """ assert info.typeddict_type + # TODO: is it possible to refactor this to set the correct type vars here? return TypeAlias( info.typeddict_type.copy_modified( fallback=mypy.types.Instance(info, info.defn.type_vars) diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 1aff1ba2862f..ff642625b379 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -6359,3 +6359,47 @@ from m import Foo [file m.py] from missing_module import Meta # type: ignore[import] class Foo(metaclass=Meta): ... + +[case testIncrementalNativeInt] +import a +[file a.py] +from mypy_extensions import i64 +x: i64 = 0 +[file a.py.2] +from mypy_extensions import i64 +x: i64 = 0 +y: int = x +[builtins fixtures/tuple.pyi] +[out] +[out2] + +[case testGenericTypedDictWithError] +import b +[file a.py] +from typing import Generic, TypeVar +from typing_extensions import TypedDict + +TValue = TypeVar("TValue") +class Dict(TypedDict, Generic[TValue]): + value: TValue + +[file b.py] +from a import Dict, TValue + +def f(d: Dict[TValue]) -> TValue: + return d["value"] +def g(d: Dict[TValue]) -> TValue: + return d["x"] + +[file b.py.2] +from a import Dict, TValue + +def f(d: Dict[TValue]) -> TValue: + return d["value"] +def g(d: Dict[TValue]) -> TValue: + return d["y"] +[builtins fixtures/dict.pyi] +[out] +tmp/b.py:6: error: TypedDict "a.Dict[TValue]" has no key "x" +[out2] +tmp/b.py:6: error: TypedDict "a.Dict[TValue]" has no key "y"