-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Reject bound covariant type variable in an argument type #734
Comments
Reject covariant type variables being used as an argument type. Reject contravariant type variables being used as a return type. Fixes python#734.
Reject covariant type variables being used as an argument type. Reject contravariant type variables being used as a return type. Fixes python#734.
Likely we don't want to be able to take I'm actually not sure whether we would reject |
I think that
|
Fixes for covariance/contravariance + #734
Reopening because the |
I don't understand why this should be rejected or what to do in its place. T = TypeVar('T', covariant=True)
class A(Generic[T]):
def foo(self, x: T) -> None: ... # Can't use as argument type! Return type is okay. There is nothing wrong with wanting to take a As far as I can see, you'd either need a way to define new type variables that are bounded on another type variable or maybe the variance part of the type variable should only apply to the first type constructor it is used in. |
@Emerentius It can result in type unsafety if there is a subclass of |
I can see it, but it's a combination of Covariance && Inheritance && Changing Variance in the child. I suppose we'll have to wait until PEP 591 to allow this? |
Mypy already supports final classes and methods, so there's no need to wait for PEP 591. I think that it may be fine to allow that for final classes and methods, but I'd like to see some real use case first that would benefit from it. @ilevkivskyi What do you think about this? |
I think there is a confusion between two things: and obvious bug, and a missing low-priority feature. The bug is that this code is clearly safe (because the variable from typing import Generic, TypeVar
S = TypeVar('S', covariant=True)
T = TypeVar('T', covariant=True)
class C(Generic[T]):
def meth(self, x: S) -> S: # mypy complains here about variance
... The workaround is trivial, just define another type variable (without
|
My usecase is recreating something akin to Rust's Result type. For this minimal example I'm using the Option type which has the same problem with fewer distracting type variables: from typing import TypeVar, Union, Generic
T = TypeVar('T', covariant=True)
class Some(Generic[T]):
def __init__(self, value: T) -> None:
self._value = value
def unwrap_or(self, _value: T) -> T:
return self._value
class Nothing:
def unwrap_or(self, value: T) -> T:
return value
Option = Union[Some[T], Nothing]
a: Option[int] = Nothing()
a.unwrap_or(3) # ok
a.unwrap_or("3") # not ok here, A bit closer to typical python, a hypothetical |
Based on a cursory inspection, the |
@Emerentius this might be helpful to you: https://github.com/dry-python/returns/blob/master/returns/maybe.py |
@JukkaL Given that the example in the OP is now correctly handled by mypy, could it be updated to a case that is not? e.g. out_T = TypeVar("out_T", covariant=True)
class A(Generic[out_T]):
def f(self, l: list[out_T]) -> None:
self.value = l[0]
a_int = A[int]()
a_object: A[object] = a_int
a_object.f(["not an int"])
a_int.value + 1 |
We should reject a bound covariant type variable in an argument type (i.e., in a contravariant position). For example, this should be rejected:
Similarly, a contravariant type variable should not be used in a return type.
The actual rule is probably a bit more involved than what I gave above, but this would probably cover most cases.
The text was updated successfully, but these errors were encountered: