-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Calling callable
in an if-condition makes mypy think branch in unreachable
#3605
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
The key problem here is that the conditional type-checking based on We can't really ever conclude that something can't be callable, short of using whole-program information about the entire class hierarchy. Even in the example given in that bug of testing a type I'm not sure if there is anything sound that we can do in response to We can soundly assume that the type is |
For constructs that we can't handle safely, we sometimes try to do something that avoids false positives and still does some useful type checking, even if it's not type safe. In the original example, inferring type In cases like def f(o: Union[str, Callable[[str], int]]) -> None:
if callable(o):
# Could be a subclass of 'str' that is callable or Callable[[str], int].
# We don't know the precise type in the first case, so we could fall
# back to Callable.
#
# We could then infer type Union[Callable[[str], int], Callable].
...
else:
# Can only be 'str' here.
... However, elsewhere we sometimes make unsafe assumptions about inheritance. For example, we sometimes assume that there is no multiple inheritance from some classes Eventually I'd like to have optional strictness flags that reject this kind of type unsafety at the cost of some extra required refactoring. I don't think that this is urgent right now, however. There still tends to be a lot of |
It looks like |
OK, found it #3603 (comment) |
I started hacking up the beginnings of a fix to this based on assuming the type of My naive implementation of this didn't work for what I think turns out is actually a pretty fundamental reason: the type maps returned by I had had it in my head that I wanted to just override the previous type with So I think that gaining any useful information from |
Yeah, given @JukkaL's confessed lack of enthusiasm for Intersection types I
think a hack along those lines sounds like a good plan.
|
Don't ever assume that something is *not* callable; basically anything could be, and getting it wrong leaves code to not be typechecked. When operating on an Instance that is not clearly callable, construct a callable version of it by generating a fake subclass with a __call__ method to be used. Fixes #3605
Don't ever assume that something is *not* callable; basically anything could be, and getting it wrong leaves code to not be typechecked. When operating on an Instance that is not clearly callable, construct a callable version of it by generating a fake subclass with a __call__ method to be used. Fixes #3605
Don't ever assume that something is *not* callable; basically anything could be, and getting it wrong leaves code to not be typechecked. When operating on an Instance that is not clearly callable, construct a callable version of it by generating a fake subclass with a __call__ method to be used. Fixes #3605
Don't assume that something is *not* callable except when operating on Union types. Normally, when operating on an Instance that is not clearly callable, construct a callable version of it by generating a fake subclass with a __call__ method. When operating on Union types, continue treating types that are not clearly callable as if they cannot be callable, so type discrimination using callable() behaves as expected. Fixes #3605
In the following code, mypy thinking
callable(o)
always returnsFalse
. This might be related to #3603.Here is the output from
mypy
andpython
.The text was updated successfully, but these errors were encountered: