diff --git a/mypy/semanal.py b/mypy/semanal.py index 9acf379b848fd..17176e9210512 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2688,7 +2688,7 @@ def configure_tuple_base_class(self, defn: ClassDef, base: TupleType) -> Instanc if info.tuple_type and info.tuple_type != base and not has_placeholder(info.tuple_type): self.fail("Class has two incompatible bases derived from tuple", defn) defn.has_incompatible_baseclass = True - if info.special_alias and has_placeholder(info.special_alias.target): + if has_placeholder(base): self.process_placeholder( None, "tuple base", defn, force_progress=base != info.tuple_type ) diff --git a/mypy/semanal_namedtuple.py b/mypy/semanal_namedtuple.py index f27c89e34fdf8..9a51bced4885d 100644 --- a/mypy/semanal_namedtuple.py +++ b/mypy/semanal_namedtuple.py @@ -527,7 +527,7 @@ def build_namedtuple_typeinfo( info = existing_info or self.api.basic_new_typeinfo(name, fallback, line) info.is_named_tuple = True tuple_base = TupleType(types, fallback) - if info.special_alias and has_placeholder(info.special_alias.target): + if has_placeholder(tuple_base): self.api.process_placeholder( None, "NamedTuple item", info, force_progress=tuple_base != info.tuple_type ) diff --git a/mypy/semanal_typeddict.py b/mypy/semanal_typeddict.py index b912ea1771874..3655e4c89dd4b 100644 --- a/mypy/semanal_typeddict.py +++ b/mypy/semanal_typeddict.py @@ -607,7 +607,7 @@ def build_typeddict_typeinfo( assert fallback is not None info = existing_info or self.api.basic_new_typeinfo(name, fallback, line) typeddict_type = TypedDictType(item_types, required_keys, readonly_keys, fallback) - if info.special_alias and has_placeholder(info.special_alias.target): + if has_placeholder(typeddict_type): self.api.process_placeholder( None, "TypedDict item", info, force_progress=typeddict_type != info.typeddict_type ) diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 1683fa40ed0b3..579693c0f29f9 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -4581,3 +4581,31 @@ bad({"x": "foo"}) # E: Dict entry 0 has incompatible type "str": "str"; expecte [builtins fixtures/dict.pyi] [typing fixtures/typing-typeddict.pyi] + +[case testTypedDictUnpackImportCycle] +import mre + +[file mre.py] +from mre_pkg.model import Callback +Callback(callback=1) # E: Argument "callback" to "Callback" has incompatible type "int"; expected "Callback" + +[file mre_pkg/model.pyi] +from typing_extensions import Unpack, TYPE_CHECKING, TypedDict +from .callbacks import Callback as Callback + +class _ModelInit(TypedDict, total=False): + callback: Callback + +class Model: + def __init__(self, **kwargs: Unpack[_ModelInit]) -> None: ... + +[file mre_pkg/callbacks.pyi] +from typing_extensions import Unpack, TYPE_CHECKING, TypedDict +from .model import Model, _ModelInit + +class _CallbackInit(_ModelInit, total=False): ... + +class Callback(Model): + def __init__(self, **kwargs: Unpack[_CallbackInit]) -> None: ... +[builtins fixtures/dict.pyi] +[typing fixtures/typing-typeddict.pyi]