infer types from super
class A:
def f(self, i: int) -> str:
...
class B(A):
@override
def f(self, i):
reveal_type(i) # int
looks like pyright already does this, so all we need to do is make it not report reportMissingParameterType on the overridden method
even though pyright is working here, there is no inlay hint on the parameter
i think there still needs to be an option to still report reportMissingParameterType in such cases, because there are libraries that have decorators that rely on type annotations for runtime checks
from pydantic import validate_call
class Foo:
@abstractmethod
def foo(self, value: int):
...
class Bar(Foo):
@override
@validate_call
def foo(self, value):
...
ideally there would be something in the type system you could put on a decorator to tell the type checker that type annotations get runtime evaluated
Isn't it the case that because of Barbara's substitution principle (I feel like I'm on a first-name basis with Liskov at this point), [email protected] could be any supertype of int in your example, @DetachHead ?
yeah it's contravariant because it's in an input position. though i still think it's safe to assume that if you don't specify the type then it should just assume it's the same as in the base class
Yea that seems reasonable. It's in line with the current behavior:
https://pyright-play.net/?pythonVersion=3.13&strict=true&deprecateTypingAliases=true&code=GYJw9gtgBAhgRgYygSwgBzCALrOBnLEGBLCAUywAswATAKFEiiwE81kA7AcxXUxzAA3MiBDIaZOnQQAbGHjxQAYmDAAuOlC1QAAvAJES5KrU3aJwKMFUAKPGRnAANFEEwZAVzJqUHLAEoNbWCoADpwqVl5RQAhGBAbFTBAsy0dIRExCVSoCytbe0cXN08yQLCIkO0pOHioAF4oOIT-OlqQUOswGwAWACZW9s7bAGZQgEYe1rogA
https://basedpyright.com/?typeCheckingMode=all&code=GYJw9gtgBAhgRgYygSwgBzCALrOBnLEGBLCAUywAswATAKFEiiwE81kA7AcxXUxzAA3MiBDIaZOnQQAbGHjxQAYmDAAuOlC1QAAvAJES5KrU3aJwKMFUAKPGRnAANFEEwZAVzJqUHLAEoNbWCoADpwqVl5RQAhGBAbFTBAsy0dIRExCVSoCytbe0cXN08yQLCIkO0pOHioAF4oOIT-OlqQUOswGwAWACZW9s7bAGZQgEYe1rogA
Apparantly mypy has a rather liberal interpretation of contravariance, and allows the following (if run with the default flags):
from abc import abstractmethod
from typing import override
class Foo:
@abstractmethod
def foo(self, value: int):
...
class Bar(Foo):
@override
def foo(self, value): ...
bar = Bar()
bar.foo(42)
bar.foo(3.14)
bar.foo('nope') # mypy doesn't care about your problems
yeah that's because mypy types it as Any if there's no annotation instead of inferring it from the base class like pyright does
class Foo:
@abstractmethod
def foo(self, value: int):
...
class Bar(Foo):
@override
def foo(self, value):
reveal_type(value) # Any
yeah that's because mypy types it as
Anyif there's no annotation instead of inferring it from the base class like pyright does
Ah I see.
I suppose that within the valid solution-space, mypy's would lie within the infemum. Or as Wolfgang Pauli once put it:
That is not only not right; it is not even wrong.