-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
[PEP 695] Fix incorrect Variance Computation with Polymorphic Methods. #19466
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
Open
randolf-scholz
wants to merge
10
commits into
python:master
Choose a base branch
from
randolf-scholz:fix_variance_polymorphic_constructor
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
d7b88cc
use plain_self as subtitution type for self
randolf-scholz a0b037e
Update mypy/subtypes.py
randolf-scholz ab680d1
Merge branch 'master' into fix_variance_polymorphic_constructor
randolf-scholz 0f33c79
Merge branch 'master' into fix_variance_polymorphic_constructor
randolf-scholz 5d16a08
Merge branch 'master' into fix_variance_polymorphic_constructor
randolf-scholz 25e8efa
Merge branch 'master' into fix_variance_polymorphic_constructor
randolf-scholz 9870139
Merge branch 'master' into fix_variance_polymorphic_constructor
randolf-scholz 0b2aead
added unit test for 18334
randolf-scholz 307382e
Merge branch 'master' into fix_variance_polymorphic_constructor
randolf-scholz 01e8651
Merge branch 'master' into fix_variance_polymorphic_constructor
randolf-scholz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This is not safe, if I continue this example like this I get an error at runtime that is not detected:
On a more general level, how exactly this:
is different from this
? Maybe I am missing something but these two are literally identical in terms of semantics. Can you give an example of uses of
Covwhere these two classes behave (or should behave) differently?Uh oh!
There was an error while loading. Please reload this page.
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 think they are only identical when called as a bound method, but not when called on the class and passing
selfas a regular argument. Note that my original example in #19439 - which is how I came across this issue -- was in the context of classmethods, and theCovtest case was really just breaking this down to the most elementary MWE.whereas
Uh oh!
There was an error while loading. Please reload this page.
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.
Consequently, I'd argue that your
Subexample is not a proper subclass ofCov.pyrightagrees thatSub.newis does not overrideCov.newin a compatible manner. Code sample in pyright playgroundSo I'd say this is actually a false negative in mypy. https://mypy-play.net/?mypy=latest&python=3.12&gist=f60a4694098406077af0b8627fc78557
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.
Access on class object is not a good argument. For two reasons:
Finally, things like
C[int].methodare not really well specified (for good reasons, google type erasure). Support for this was added to mypy only recently, following a popular demand.Btw #18334 is not a bug, it is a true positive. Coming back to your original issue: the two revealed types here are different (and both IMO correct):
and this is the reason why a class with the first method is considered invariant. I understand why do you want to have the first one: the body should include something like
return cls(arg)which would give an error with the second method.TBH I don't think this is solvable without special-casing alternative constructors somehow. Also it looks like a flaw in PEP 695, there should be a simple way to override inferred variance.
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.
@ilevkivskyi your unsafety example is very similar to what I pointed out before, and the problem is roughly "yes, this is obviously unsafe, but the spec says so". What's the official mypy stance on the spec conformance? I prefer to read the spec as an advice, not a mandatory requirement, but IDK if that matches the project attitude.
If mypy considers spec conformance its goal, then this PR is correct, and a typing-sig discussion is needed to fix this spec unsoundness. If not, this PR makes the state of affairs worse, trading false positives for false negatives.
There is, it's called
typing.TypeVar. AFAIC this ability was one of the reasons to not even consider deprecating "old-style" generics. I think it's rare enough to not warrant any extra syntax (though I'm a bad person to ask about that, IMO PEP695 should have never been implemented at all), so not a PEP omission.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.
@sterliakov
Yes, this is the official mypy stance: internal consistency is more important than consistency with the spec.
OK, I see :-)
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.
Feel free to comment or👍 my suggestion for explicit variance spec for PEP695 type hints in discourse.