You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Mypy inappropriately infers class type as _typeshed.DataclassInstance #14941
Bug Report
In the following code snippet, mypy incorrectly infers the type of typ as _typeshed.DataclassInstance. This issue was not present in previous versions of mypy
Mypy is narrowing the type of typ to type[DataclassInstance] because the is_dataclass function which was recently changed to use a TypeGuard. This is why the behavior changed with recent versions of mypy. Here's the relevant overload from dataclasses.pyi:
i think that narrowing from type[T] to type[DataclassInstance] is problematic becuase DataclassInstance is a Protocol. type[DataclassInstance] is not always a subtype of type[T]1.
would this be solved if type narrowing used intersections (python/typing#213)?
Footnotes
depending on the bound on T. if T is unbound then type[DataclassInstance] is a subtype of type[T], but if we had a bound T = TypeVar("T", bound=A) and A wasn't a subtype of DataclassInstance, then type[DataclassInstance] would legitimately not be a subtype of type[T]. ↩
here's a small reproducer that isn't tied to the recent typeshed changes:
@runtime_checkableclass_HasFoo(Protocol):
# some structural type that is third-party private and not available for users to use in annotations.@classmethoddeffoo(cls) ->None:
...
defclass_has_foo(typ: type, /) ->TypeGuard[type[_HasFoo]]:
# some TypeGuard for type[it] that is third-party public.returnissubclass(typ, _HasFoo)
defconstruct(typ: type[T], /) ->T:
ifnotclass_has_foo(typ):
raiseTypeError()
returntyp()
would this be solved if type narrowing used intersections
Yes, intersections would solve this.
pyright and pyre error with this too.
I just checked in a fix for pyright that addresses this issue. Pyright has the concept of conditional types, which is effectively an internal intersection between a TypeVar and another type.
Activity
erictraut commentedon Mar 23, 2023
Mypy is narrowing the type of
typtotype[DataclassInstance]because theis_dataclassfunction which was recently changed to use aTypeGuard. This is why the behavior changed with recent versions of mypy. Here's the relevant overload fromdataclasses.pyi:gschaffner commentedon Mar 23, 2023
i think that narrowing from
type[T]totype[DataclassInstance]is problematic becuaseDataclassInstanceis aProtocol.type[DataclassInstance]is not always a subtype oftype[T]1.would this be solved if type narrowing used intersections (python/typing#213)?
Footnotes
depending on the bound on
T. ifTis unbound thentype[DataclassInstance]is a subtype oftype[T], but if we had a boundT = TypeVar("T", bound=A)andAwasn't a subtype ofDataclassInstance, thentype[DataclassInstance]would legitimately not be a subtype oftype[T]. ↩gschaffner commentedon Mar 23, 2023
here's a small reproducer that isn't tied to the recent typeshed changes:
(https://mypy-play.net/?mypy=1.1.1&python=3.11&gist=e1d8c7379c14222d2ec5f2e91eca4f62)
pyright and pyre error with this too.
erictraut commentedon Mar 23, 2023
Yes, intersections would solve this.
I just checked in a fix for pyright that addresses this issue. Pyright has the concept of conditional types, which is effectively an internal intersection between a TypeVar and another type.
binishkaspar commentedon Mar 23, 2023
I think for now I will introduce a new function
guardsafe_is_dataclass(may be need a better name) which returns bool without using TypeGuarddszady-rtbh commentedon Dec 5, 2023
Can we expect this to be fixed?
Narrow type variable bounds in binder (python#19183)