-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Labels
priority-1-normaltopic-inheritanceInheritance and incompatible overridesInheritance and incompatible overrides
Description
Covariant overriding of attributes is allowed though it's clearly unsafe. Example:
class A:
x: float
class B(A):
x: int # no error, though unsafe
def f(a: A) -> None:
a.x = 1.1
b = B()
f(b)
b.x # float at runtime, though declared as int
Mypy should reject x: int
in B
. If this is actually what the programmer intended, they can use # type: ignore
.
KotlinIsland, DetachHead, lemon24, andreivasiliu, LeeeeT and 8 more
Metadata
Metadata
Assignees
Labels
priority-1-normaltopic-inheritanceInheritance and incompatible overridesInheritance and incompatible overrides
Projects
Milestone
Relationships
Development
Select code repository
Activity
ilevkivskyi commentedon Apr 21, 2017
I agree with the idea, but I think we should have a flag to allow this (
--alow-mutable-overriding
?), otherwise it could be a bit annoying to put# type: ignore
s. It will be easy to implement such a flag.JukkaL commentedon Apr 21, 2017
I don't agree with having a flag -- I don't see why this particular case of unsafety should have a flag dedicated to it. I don't expect that this will require many
# type: ignore
s for most users, and a better fix is to not redefine attributes covariantly (or to use a read-only property).ilevkivskyi commentedon Apr 21, 2017
Probably a good measure for this would be to just test a future PR against mypy itself and Dropbox internal codebase. If there will be not many errors due to prohibiting covariant overriding of mutable attributes, then probably it is OK to not have a flag.
JukkaL commentedon Apr 21, 2017
We have previously had to make maybe hundreds of changes to Dropbox internal repos in response to fixes to mypy, so our bar for adding a backwards-compatibility flag is pretty high.
ilevkivskyi commentedon Apr 21, 2017
Ah, OK, I see.
JukkaL commentedon Jun 4, 2019
This is less controversial now, since in many use cases it's possible to use
Final
attributes, for which we can allow safe covariant overriding. This still wouldn't help when the attribute needs to be modified, but I believe that these use cases are somewhat rare, and it's still possible to use a# type: ignore
comment as a workaround.18 remaining items
JelleZijlstra commentedon Sep 12, 2023
This also just came up in mypyc/mypyc#1019: evidently when compiling with mypyc, we already perform this check.
A good next step for anyone interested in this would be to make a PR that unconditionally enables this check, then see how bad the fallout is in mypy-primer. Then we can decide how to handle this, maybe by adding a new flag or maybe by enabling it unconditionally. (I know Jukka above opposed adding a new flag, but there's a lot more typed Python code than when he wrote that, so turning this on unconditionally may be too disruptive now.)
mikeshardmind commentedon Sep 12, 2023
Having it configurable is problematic as this is a base behavior that other things need to be able to rely on being correct.
JukkaL commentedon Sep 13, 2023
Can we add a new error code for this check? This way we wouldn't need an additional flag.
hauntsaninja commentedon Sep 14, 2023
I implemented a version of this. I got about 300 errors in 49 / 131 projects in mypy_primer.
While my implementation was pretty quick and dirty (there are soundness holes I didn't plug and I didn't do much dedicated testing), it matched the results of microsoft/pyright#5934 (pyright only runs on 27 of projects in mypy_primer). The only difference was we report a couple extra errors on steam.py, which looked correct to me (e.g. my patch complains about https://github.com/Gobot1234/steam.py/blob/336064153a1fea5c751a5c5f60a71c1afe4b0c7f/steam/_gc/client.py#L41 but pyright's patch does not).
This is more disruptive than other disruptive changes I can remember, like the ones in 0.991. I also checked a couple of these and couldn't find any "real" bugs. So I would be opposed to having it on by default. I'll try scoping it to part of
--strict
and see what that looks like. And of course, no harm as having it be an opt-in error code.reportIncompatibleVariableOverride
when narrowing type fromClassVar[str]
toClassVar[Literal["bar"]]
in subclasses microsoft/pyright#5998beauxq commentedon Oct 11, 2023
This is not true because
Final
also prevents overriding.python/typing#1486
https://mypy.readthedocs.io/en/stable/final_attrs.html
It would be nice to have something to indicate that a value can't be changed, but can be overridden. Some have suggested
typing.ReadOnly
alicederyn commentedon Oct 26, 2023
This would IMO be a very reasonable follow-up to PEP-705.
Add error code for mutable covariant override (#16399)
Any & T
CarliJoy/intersection_examples#31[mutable-override]
#18052