diff --git a/mypy/checker.py b/mypy/checker.py index d13b927b28f2..212ddd65d912 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -3133,7 +3133,7 @@ class C(B, A[int]): ... # this is unsafe because... x: A[int] = C() x.foo # ...runtime type is (str) -> None, while static type is (int) -> None """ - if name in ("__init__", "__new__", "__init_subclass__"): + if name in {"__init__", "__new__", "__init_subclass__", "__replace__"}: # __init__ and friends can be incompatible -- it's a special case. return first = base1.names[name] diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 54b3afadc8b3..5ac031842116 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -2609,6 +2609,27 @@ class Y(X): [builtins fixtures/tuple.pyi] +[case testDunderReplaceDoesNotBlockPlainIssubclassNarrowing] +# https://github.com/python/mypy/issues/21635 +# flags: --python-version 3.13 +from dataclasses import dataclass + +@dataclass +class A: ... +@dataclass +class M: ... +@dataclass +class B(A): ... +@dataclass +class C(M, A): ... + +cls: type[A] = C +if issubclass(cls, M): + reveal_type(cls) # N: Revealed type is "type[__main__.]" + n: int = 'foo' # E: Incompatible types in assignment (expression has type "str", variable has type "int") +[builtins fixtures/isinstancelist.pyi] + + [case testFrozenWithFinal] from dataclasses import dataclass from typing import Final