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
it's not possible to define an 'add' that works with more than one kind of number when using number types directly #12899
Comments
I guess the workaround looks like this? from typing import TypeVar, Protocol
Self = TypeVar("Self")
class Addable(Protocol):
def __add__(self: Self, other: Self) -> Self:
...
Num = TypeVar("Num", bound=Addable)
def add(a: Num, b: Num) -> Num:
return a + b This seems to work? It still has the problem of "mixing |
Another workaround (that still allows mixing from typing import TypeVar
Num = TypeVar("Num", int, float)
def add(a: Num, b: Num) -> Num:
return a + b
reveal_type(add(1, 2)) # N: Revealed type is "builtins.int"
reveal_type(add(1, 2.0)) # N: Revealed type is "builtins.float"
reveal_type(add(1.0, 2)) # N: Revealed type is "builtins.float"
reveal_type(add(1.0, 2.0)) # N: Revealed type is "builtins.float" I think mypy is somewhat correct in erroring on your original example because subclassing from typing import TypeVar
# mypy is probably treating int | float the same as float here
Num = TypeVar("Num", bound=float)
class C(float):
pass
def add(a: Num, b: Num) -> Num:
return a + b # E: Incompatible return value type (got "float", expected "Num")
reveal_type(add(C(), C())) # N: Revealed type is "__main__.C" mypy infers The workaround with an |
I think mypy is doing the right thing here. I don't consider this a bug. |
The OP's example with latest mypy (https://mypy-play.net/?mypy=latest&python=3.10&gist=433772fa66fc4f012b485d036496cc89) still produces these errors:
I think the first error is correct but the second is a bug. Pyright only produces a single error, equivalent to the If you change the return type to |
Bug Report
I can't figure out how to write generic numeric code.
This is already covered to some extent by #3186, but that's about a higher-level numeric tower issue, rather than the very practical issue of code that can just work with
int
orfloat
but has to keep the number type straight.To Reproduce
I actually want
| Decimal | Fraction
in there, but that makes the problem worse.The same issue seems to occur with
Generic
s.Expected Behavior
No errors.
Actual Behavior
I understand how this would not work if I were using division, or if there were some other variance on
Num
but is there really some way to add an int to an int and get a float?Your Environment
mypy.ini
(and other config files): NoneThe text was updated successfully, but these errors were encountered: