-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Value-Constrained TypeVar incorrectly narrowed down by isinstance checks #10302
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
Comments
I think mypy's behavior is correct in this case, although the error message is a bit confusing. The signature for Here's an alternative solution that might meet your needs: class Operator:
@overload
def process(self, obj: A) -> A: ...
@overload
def process(self, obj: B) -> B: ...
def process(self, obj: Union[A, B]) -> Union[A, B]:
if isinstance(obj, A):
return A()
elif isinstance(obj, B):
return B() |
@erictraut Thank you for the help! That makes sense, and we can switch to using from typing import TypeVar
class A:
pass
class B:
pass
OperableT = TypeVar("OperableT", A, B)
class Operator:
def process(self, obj: OperableT) -> OperableT:
if type(obj) == A:
return A()
elif type(obj) == B:
return B()
else:
raise TypeError Results:
|
Got it -- the fact that the errors appear does make sense then, it just seems like the error messages are pretty divorced from the underlying issues. Thanks for the help! |
i think this issue can be closed as the behavior is correct. i raised #11536 for the bad error message alternatively we can rename this issue and close mine? |
The two linked issues regarding type narrowing using Consider this even simpler, though ultimately very similar, code:
For this code, mypy complains of a type error on only one (!?) branch of the select:
Note that in line 13, the type is already correctly narrowed to I do not believe the original argument that:
is correct. In all of the examples, a constrained type is used. Constrained types "can only ever be solved as being exactly one of the constraints given". So the signature (in my example) must solve to either: If I change this code to be intentionally wrong, then I get an error that hints at what the bug might be. If, in my code above, I change line 13 to be
The first and last are as expected, but the middle one is unexpected—it looks like mypy is trying to check the case where the solutions for |
Bug Report
When using a TypeVar with a value restriction to multiple classes, isinstance checks seem to incorrectly narrow down the TypeVar. Possibly connected to #10287
To Reproduce
Expected Behavior
Mypy should be able to resolve the type of the OperableT TypeVar and correctly validate the return value in the process() method.
Actual Behavior
Mypy instead throws a return error for the above:
error: Incompatible return value type (got "A", expected "B") [return-value]
For some reason, in the first isinstance check, mypy seems to resolve the OperableT TypeVar to "B" instead of "A."
mypy.ini
(and other config files): noneThe text was updated successfully, but these errors were encountered: