-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Support for covariant and contravariant TypeVar's #694
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
Conversation
…checking (is_subtype).
…th the new 'invariant' default for type variables (was covariant).
_T = TypeVar('_T') | ||
_KT = TypeVar('_KT') | ||
_VT = TypeVar('_VT') | ||
_T = TypeVar('_T', covariant=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mutable collections should have invariant type variables (e.g., MutableSequence
).
Thanks for implementing this! This is important as this is one of the biggest features missing from PEP 484 support. I did a quick pass and it looks pretty good! There are a bunch of additional things that should probably go in at some point. It's probably best to leave these out of this PR, as the current PR is already a significant improvement over what was before. (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. (2) Like (1), but for attributes. In a covariant class an instance attribute with type (3) In generic inheritance, we can't change the variance of a type from invariant to covariant/contravariant. This should probably be rejected:
Going from covariant to invariant is fine (for example, (4) Covariant type variable should not be used in the return type in an invariant position, for example like this:
There is probably a similar rule for contravariance. Notes: There are probably some additional corner cases, but the above should cover the most interesting bits. And I'm not 100% sure that the above are correct... haven't thought about this very carefully yet. Don't hesitate to ask if some the above doesn't make any sense -- this is actually a pretty tricky feature :-) |
@JukkaL I agree that it's best to leave those additional checks out and have this PR focussed on the relations between generic types. I've started updating |
… variables. For example, the join of G[A] and G[B] is now G[A] if B is a subtype of A.
…taken into account.
…urate and to prevent a confusion with subtypes.is_proper_subtype function.
I made a few fixes to |
Cool, thanks for the updates. Things are currently seriously hectic in my life, so I can't promise that I'll be able to review this very soon. I'm moving away from my current place in two weeks and after that I'll be traveling for another two weeks (and I'll need to prepare two workshop talks about mypy that I'll give at ECOOP in Prague), but I'll try to find some time. |
Take your time and good luck with your workshops. |
Are you planning on working with #689 as well? |
Finally had the time to finish reviewing this! I did some updates to stubs to avoid having covariant type variables in argument types. I'll add further work (as discussed above) as separate issues. |
This PR adds support for covariant and contravariant type variables, like:
See the test cases I added for other examples.
Note that also the default has changed from covariant to invariant (as specified by the PEP). I made the minimal changes to
typing.py
to make it work (the type variables were covariant by default and I've defined them now explicitly as such). But we should probably copy in the version from ambv/typehinting.There are still a few things to do (see below), but I won't be able to work on this until Tuesday and I don't expect big changes so it can be reviewed.
Todo
Especially for code paths that useis_proper_subtype
, for which there are no tests at all currently.Also subtype test; now there're only tests for covariant type variables.Fix type error (Cannot determine type of 'INVARIANT'
)True = 1
with something betterIn-> Names are not identical (qualified vs. unqualified it seems)semanal.py
, there are several functions that return aList[Tuple[str, TypeVarExpr]]
, where the string is the type variable name. The string can probably be refactored out, asTypeVarExpr
already contains the name.Fixes #643.