-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
(🐞) overload
s that exhaust finite Literal
s(bool
/Enum
) not treated as exhaustive
#14764
Comments
Is this issue really specific to |
You are correct that in this example, mypy is not able to correctly handle the case where the argument a is a boolean value and not a Literal. This is because the Literal types in the overloads are not being unioned with the bool type in the function definition. To address this issue, you can modify the function definition to include a union type that includes all possible values of a: from typing import Literal, overload, Union
@overload
def foo(a: Literal[True]) -> int: ...
@overload
def foo(a: Literal[False]) -> str: ...
def foo(a: Union[bool, Literal[True], Literal[False]]) -> Union[int, str]:
if a is True:
return 42
else:
return "Hello, world!"
a: bool
reveal_type(foo(a)) # This now correctly shows Union[int, str] In this version, we have modified the foo function definition to include a union type that includes all possible values of a. We have also modified the return type to be a union of the possible return types from the two overload functions. Now, mypy is able to correctly handle the case where a is a boolean value and not a Literal. |
Literal
True
and False
not an exhaustive bool
when in overload
sLiteral
overloads not treated as exhaustive
It works correctly with unions, but not other exhaustible from typing import *
from enum import Enum
class A(Enum):
a = 1
@overload
def foo(a: Literal[A.a]) -> int: ...
@overload
def foo(a: A) -> object: ... # no error
def foo(a: object) -> object: ...
a: A
reveal_type(foo(a)) # object |
Literal
overloads not treated as exhaustiveoverload
s that exhaust finite Literal
s(bool
/Enum
) not treated as exhaustive
I also stumbled upon this. There is also a problem with type inference or so: @overload
def test_overload(is_fun: Literal[True]) -> str:
...
@overload
def test_overload(is_fun: Literal[False]) -> int:
...
def test_overload(is_fun: bool = True) -> str | int:
return "1" if is_fun else 1 this yields no error, but as soon as we use def foo(bar: bool = True) -> str | int:
return test_overload(bar)
####
t.py:76: error: Returning Any from function declared to return "Union[str, int]" [no-any-return]
t.py:76: error: No overload variant of "test_overload" matches argument type "bool" [call-overload]
t.py:76: note: Possible overload variants:
t.py:76: note: def test_overload(is_fun: Literal[True]) -> str
t.py:76: note: def test_overload(is_fun: Literal[False]) -> int
Found 2 errors in 1 file (checked 1 source file) What could go wrong here? The only way to get out of this situation is to add an overload that access @overload
def test_overload(is_fun: bool) -> str | int:
... |
I might not be following entirely. Isn't this correct behavior? There are two cases to be handled for all non-literal types - the value is known statically, and the value is not known statically. Covering the two literal cases with overloads could only ever be used for the former, and not for the latter. The bool case is necessary for when the value is not known. If instead of taking a |
@gandhis1 That's not how finite types work, and |
Looks like the same issue in pyright, but for them it's regression now: microsoft/pyright#5421 |
Likely related: #15456 |
Here mypy incorrectly forces us to implement a completely redundant overload for the non
Literal
case when it is already exhaustively covered by both literals. It is only when the literals are in the same overload (useless in practice, but just for demonstration) that mypy correctly handles this case.Mypy should be doing 'union math' (or what ever it's called) to apply both literal overloads at once.
This also affects all other exhaustible
Literal
s such asEnum
s.This example is pulled directly from the docs, so I think they should be updated as well to an example that doesn't contain this confusing defect.
The text was updated successfully, but these errors were encountered: