-
Notifications
You must be signed in to change notification settings - Fork 235
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
Updated spec and conformance test to reflect that a type variable tha… #1587
Conversation
…t is defined as covariant or contravariant should not generate an error when bound to a generic function or type alias. Variance has no meaning in this context, so it should be ignored. This brings the spec in alignment with the behavior of the major type checkers.
Linking python/typing-council#8 |
docs/spec/generics.rst
Outdated
For example, the following example is | ||
fine:: | ||
Variance is meaningful only when a type variable is bound to a generic class. | ||
Variance has no meaning, and should therefore be ignored by type checkers, if |
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.
I'd be okay with this PR if you just remove "should therefore be ignored w by type checkers", so type checkers may choose to reject typevars declared as covariant or contravariant in contexts where variance has no meaning.
Variance has no meaning, and should therefore be ignored by type checkers, if | |
Variance has no meaning if |
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.
If type checkers do not ignore variance when it has no meaning, what should they do instead? Keep in mind that every TypeVar (prior to PEP 695's "inferred variance") has an explicit variance; it's either invariant, covariant, or contravariant.
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.
Since "invariant" is declared by not adding {co,contra}variant=True
to the TypeVar()
call, I'd propose that type checkers accept invariant (i.e., default) typevars but issue an error for co/contra-variant typevars.
I believe it is reasonable to assume that omitting any mention of variance in the TypeVar()
call is less explicit than explicitly using one of the two variance-declaring options (there is no invariant=True
option).
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.
I was curious, so I quickly implemented a check in pyright for a TypeVar that's covariant or contravariant if it is scoped to a generic function or type alias. Here's the mypy_primer result: microsoft/pyright#6993. This isn't as noisy as I predicted. Interestingly, 100% of the violations it caught were in type aliases rather than functions.
I think we should make it clear in the spec that variance has no meaning for TypeVars scoped to functions or type aliases — and that type checkers should therefore ignore the variance for purposes of type checking. As for additional checks, I think we have three options:
- Indicate that type checkers should warn users if they attempt to use a covariant or contravariant TypeVar scoped to a generic function or type alias.
- Indicate that type checkers may warn users in this circumstance (but not mandate it).
- Indicate that type checkers should be silent about this circumstance, since variance is meaningless in this context.
I guess I don't have a strong opinion. The current draft text aligns to 3. It sounds like you prefer 1? Or 2?
I do think that mypy's current behavior is hard to defend. It emits an unrelated (and kind of meaningless) error if a covariant TypeVar is used for an input parameter or if a contravariant TypeVar is used for a return type. Since variance isn't meaningful in this case, those errors are inappropriate and confusing, IMO.
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.
I'd go for (2), or (2a) don't allude to what type checkers should do at all.
(I'm beginning to realize that "has no meaning" is a rather ambiguous phrase, which implies different things in different contexts -- at least to me. I don't think it's the same as "is redundant" here.)
I agree that mypy's error is not what I thought it was and should be fixed independently.
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.
LG on the spec text now.
@gvanrossum, if you're OK with this wording, please sign off on the TC decision here: python/typing-council#8. Thanks! |
@JelleZijlstra & @rchen152, let me know if you have any suggested improvements. If you're OK with the latest wording, please sign off on the TC decision. |
…variance_2 # Conflicts: # conformance/results/pyright/generics_variance.toml # conformance/results/results.html
…t is defined as covariant or contravariant should not generate an error when bound to a generic function or type alias. Variance has no meaning in this context, so it should be ignored. This brings the spec in alignment with the behavior of the major type checkers.