From d266f647eb56e7710b1ef6cccbface689da67a0f Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Sun, 2 Nov 2025 23:19:45 -0800 Subject: [PATCH] Fix type checking of dict type aliases Resolves a bad false negative and a false positive Previously, for `D = dict[str, str]` we would require a type annotation for `d = D()` and we would fail to error on `D(x=1)` Fixes #11093, fixes #11246 --- mypy/semanal.py | 6 +++++- test-data/unit/check-type-aliases.test | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index d7b50bd09496..bf59985cef54 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -5842,7 +5842,11 @@ def visit_call_expr(self, expr: CallExpr) -> None: expr.analyzed = PromoteExpr(target) expr.analyzed.line = expr.line expr.analyzed.accept(self) - elif refers_to_fullname(expr.callee, "builtins.dict"): + elif refers_to_fullname(expr.callee, "builtins.dict") and not ( + isinstance(expr.callee, RefExpr) + and isinstance(expr.callee.node, TypeAlias) + and not expr.callee.node.no_args + ): expr.analyzed = self.translate_dict_call(expr) elif refers_to_fullname(expr.callee, "builtins.divmod"): if not self.check_fixed_args(expr, 2, "divmod"): diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 5bbb503a578a..06e223716189 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -1318,3 +1318,17 @@ from typing_extensions import TypeAlias Foo: TypeAlias = ClassVar[int] # E: ClassVar[...] can't be used inside a type alias [builtins fixtures/tuple.pyi] + + +[case testTypeAliasDict] +D = dict[str, int] +d = D() +reveal_type(d) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" +reveal_type(D()) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" +reveal_type(D(x=1)) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]" +reveal_type(D(x="asdf")) # E: No overload variant of "dict" matches argument type "str" \ + # N: Possible overload variants: \ + # N: def __init__(self, **kwargs: int) -> dict[str, int] \ + # N: def __init__(self, arg: Iterable[tuple[str, int]], **kwargs: int) -> dict[str, int] \ + # N: Revealed type is "Any" +[builtins fixtures/dict.pyi]