Skip to content

Commit

Permalink
Fix generic TypedDict/NamedTuple fixup (#14675)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ilevkivskyi authored Feb 14, 2023
1 parent 0b4ccae commit ec511c6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
4 changes: 4 additions & 0 deletions mypy/fixup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
14 changes: 12 additions & 2 deletions mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3495,8 +3495,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,
Expand All @@ -3506,8 +3511,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)
Expand Down
31 changes: 31 additions & 0 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -6372,3 +6372,34 @@ 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"

0 comments on commit ec511c6

Please sign in to comment.