Repository navigation
Incorrect inference with isinstance() #2993
Description
Activity
Yes, the way type objects are represented right now is kind of messy. Until we clean up the implementation, mypy should support all the possible representations of type objects in all contexts.
The second case would be a reasonable thing to fix if the fix is simple enough, though clearly it's not a high priority thing. Could you actually create a separate issue for the second case, since it seems like an independent issue?
Actually, I was wrong: the 1) issue has nothing to do with whether
typeis aCallableTypeor anInstance(and I understand now why it's not quite a good fit forCallableType). The problem is that from the perspective of type checker, the second argument toisinstancecan be either a literal type (when the source code directly refers to a class name), or a variable that contains the type (when the source code uses a function argument or something else). In the second case, the type checker cannot really infer anything since the value inside the variable won't be known statically. So I don't think there's any need to fix the representation oftype, just a small logic change to the function will fix the problem.And yes, I can separate them out.
Ah yeah, I didn't read the first example correctly. Yes, if one the types is a
typeinstance, it can match any type, but it could also not match any type. For example:from typing import * def f(x: Union[int, str], typ: type) -> None: if isinstance(x, (typ, int)): reveal_type(x) # should be Union[int, str] else: reveal_type(x) # should be strI'm moving item 2) into a separate issue as you suggested.
What's the issue# for the separate issue you created for (2)? Also does #2997 fix this or (2) or both?
I think there are a few problems with
isinstanceinference.mypy --strcit --python-version 3.6, but it should not:The semantic analyzer concludes that within the body of
if isinstance(), the type ofxmust beint. It's not, however. For example, in this casef('a', str), theifbranch will be followed even thoughxis not anint(and this will cause runtimeTypeErrorwithout any mypy warnings).The reason this happens is that
typeannotation is represented as anInstancerather than as aFunctionLikeinsidechecker.py:get_isinstance_type(). As a result, it's skipped entirely in the loop, and onlyintis added totypes, so sem analyzer thinksxmust absolutely beint.One solution is to make
typerepresented with an instance ofCallableType(why isn't it btw?!). Another solution is to simply add a bit of logic to the loop to properly handle this case.results in
error: Argument 2 to "isinstance" has incompatible type "Tuple[str, Tuple[List[_T], Tuple[_T_co, ...]]]"; expected "Union[type, Tuple[type, ...]]".This is because there's this weird thing in python that allows to put nested tuples as the second argument to
isinstance, andmypy(along with most other people) doesn't know about it. I don't know if it's worth fixing, but it's super easy (just flatten the second argument if it's a tuple).If my understanding is correct, I'll make a PR.