python / typeshed

Collection of library stubs for Python, with static types
Other
4.29k stars 1.72k forks source link

`is_dataclass(Any)` return type incorrect, differs from `is_dataclass(object)` #12401

Closed intgr closed 3 weeks ago

intgr commented 1 month ago

I found this surprising and arguably incorrect. According to mypy:

from typing import Any
from dataclasses import is_dataclass

def example1(arg: Any) -> None:
    if is_dataclass(arg):
        reveal_type(arg)  # ❌ Revealed type is "type[_typeshed.DataclassInstance]"

def example2(arg: object) -> None:
    if is_dataclass(arg):
        reveal_type(arg)  # ✅ Revealed type is "Union[_typeshed.DataclassInstance, type[_typeshed.DataclassInstance]]"

(Mypy playground)

This is because Any matches the 1st overload, even if 2nd overload with object argument is more appropriate for Any:

@overload
def is_dataclass(obj: type) -> TypeIs[type[DataclassInstance]]: ...
@overload
def is_dataclass(obj: object) -> TypeIs[DataclassInstance | type[DataclassInstance]]: ...

I couldn't think of an elegant fix for this.

srittau commented 1 month ago

I don't think there is a fix, as Any is compatible with everything, so it will always match the first overload. Reordering is also not possible, at least not until we get a "Not" type (python/typing#801).

intgr commented 1 month ago

As a hack, we could add another overload case, with argument type that no real type ever satisfies but only Any can satisfy. Could we use the Never type?

sobolevn commented 1 month ago

Refs https://github.com/python/mypy/issues/17579

max-muoto commented 1 month ago

For reference Pyright is handling this just fine: https://pyright-play.net/?pyrightVersion=1.1.374&pythonVersion=3.14&strict=true&code=GYJw9gtgBALgngBwJYDsDmUkQWEMoCCKcAUKJFACYCGM1AxgDbUDOLApi5trvkiwH0adJqxYkJldsCjsAHtWyN2ARgAU1EGgBchYgEooAWgB8UAHJgU7bSSj3MM-kNoNmbDVv22HvqCHYAN3ZqRgF4BHZPNEMoCRIpGXlFBGUAJmjdMAAjACt2ehhDUwsrGzsHJCdBYTcxaO8Kv38gkLCIqKbmh000Lt9DEiA

srittau commented 1 month ago

@intgr We could try your suggestion in an experimental PR. (We should definitely add tests, though.) Otherwise I would close this issue as unfixable.

intgr commented 4 weeks ago

Opened PR:

sobolevn commented 3 weeks ago

MyPy PR is here: https://github.com/python/mypy/pull/17678