From 18c46938e77a3ab01e6e38b57c0b3f1286966109 Mon Sep 17 00:00:00 2001 From: Stas Ilinskiy Date: Wed, 15 Feb 2023 08:41:49 -0800 Subject: [PATCH] [Backport] Fix generic TypedDict/NamedTuple fixup (#14701) Backport of #14675. --------- Co-authored-by: Ivan Levkivskyi --- mypy/fixup.py | 4 ++++ mypy/nodes.py | 14 ++++++++++-- test-data/unit/check-incremental.test | 31 +++++++++++++++++++++++++++ 3 files changed, 47 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..2897e895a394 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -6359,3 +6359,34 @@ from m import Foo [file m.py] from missing_module import Meta # type: ignore[import] class Foo(metaclass=Meta): ... + +[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"