-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Overconstrained type variable #5775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
(Edited the repro to be closer to what is actually wanted.) |
Is there a workaround for this? I'm having a similar problem: from typing import Mapping, Sequence, TypeVar, Union
from typing_extensions import Protocol
Row = TypeVar("Row", bound=Union[Sequence, Mapping])
class C(Protocol[Row]):
...
Any (perhaps dirty) way to make this work? |
Make your type variable covariant. (I don't think your case falls under what Ivan's talking about in this issue) |
I also have such a trouble with mypy 0.950 and Python 3.9. from collections.abc import Iterable
from typing import Protocol, TypeVar, overload
K = TypeVar('K')
V = TypeVar('V')
class SupportsKeysAndGetItem(Protocol[K, V]):
def keys(self, /) -> Iterable[K]: ...
def __getitem__(self, item: K, /) -> V: ...
@overload
def foo() -> dict: ...
@overload
def foo(**kwargs: V) -> dict[str, V]: ...
@overload
def foo(mapping: SupportsKeysAndGetItem[K, V], /) -> dict[K, V]: ...
@overload
def foo(mapping: SupportsKeysAndGetItem[str, V], /, **kwargs: V) -> dict[str, V]: ...
@overload
def foo(iterable: Iterable[tuple[K, V]], /) -> dict[K, V]: ...
@overload
def foo(iterable: Iterable[tuple[str, V]], /, **kwargs: V, ) -> dict[K, V]: ...
def foo(iterable = (), /, **kwargs):
return dict(iterable, **kwargs) Produces |
Closing as per my previous comment |
@hauntsaninja I am pretty sure that mypy overcontrains Protocol variables. Check this case in mypy-play.net. from typing import Protocol, TypeVar
K = TypeVar('K')
V = TypeVar('V')
class Protocol1(Protocol[K, V]):
def foo1(self, /) -> K: ...
def foo2(self, value: K, /) -> V: ...
def foo3(self, value: V, /) -> K: ... No errors. If
If
If I make
All in all, once a user introduces methods with Protocol variables as argument types, then error about covariance is not emitted. I personally do not see any sense in constraining Protocol variable to be covariant (unless there are methods with them). I find OK for arbitrary protocol |
Those errors are all correct; I'm not sure what your complaint is. |
I wonder why Protocol type variables must be covariant unless there are methods with them as argument types. |
They can be covariant when they are used only in return types, and they can be contravariant when they are used only in argument types; they must be invariant when used in both positions. That's just normal variance rules. What's perhaps less intuitive is that mypy enforces that when the TypeVar can be covariant, it must be covariant. I didn't make that decision, but I think the reasoning is that usually covariance is what you want if it's possible, and it's helpful to users to point out when they accidentally use invariance. |
This decision seems to prevent users from declaring Protocols that share an invariant generic type. For a simple practical example, a depth-first search framework:
This results in the following mypy errors:
Is there a workaround for this? |
Python 3.6.6 x64
Windows 10 x64
mypy 0.630
mypy-extensions 0.4.1
typing 3.6.6
typing-extensions 3.6.6
https://mail.python.org/pipermail/python-ideas/2018-October/054134.html
Ivan Levkivskyi's suggested solution to handling a "PathLike" protocol:
Produces an error unexpected error:
Ivan's response
The text was updated successfully, but these errors were encountered: