Skip to content

Commit 5797c39

Browse files
committed
Fix type inference, isinstance and typevar values
If a if block, that is skipped due to an isinstance test that is always False, contains the primamry initialization of a variable, the second initializer in the else block is used to infer the type of variable instead.
1 parent 181ef0e commit 5797c39

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

mypy/checker.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,11 +502,19 @@ def check_assignments(self, lvalues: List[Node],
502502

503503
def is_definition(self, s: Node) -> bool:
504504
if isinstance(s, NameExpr):
505-
return s.is_def
505+
if s.is_def:
506+
return True
507+
# If the node type is not defined, this must the first assignment
508+
# that we process => this is a definition, even though the semantic
509+
# analyzer did not recognize this as such. This can arise in code
510+
# that uses isinstance checks, if type checking of the primary
511+
# definition is skipped due to an always False type check.
512+
node = s.node
513+
if isinstance(node, Var):
514+
return node.type is None
506515
elif isinstance(s, MemberExpr):
507516
return s.is_def
508-
else:
509-
return False
517+
return False
510518

511519
def expand_lvalues(self, n: Node) -> List[Node]:
512520
if isinstance(n, TupleExpr):

mypy/test/data/check-typevar-values.test

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,43 @@ def f(x: T) -> T:
148148
[out]
149149
main: In function "f":
150150

151+
[case testIsinstanceAndTypeVarValues3]
152+
from typing import typevar, Undefined
153+
T = typevar('T', values=(int, str))
154+
def f(x: T) -> T:
155+
if isinstance(x, int):
156+
y = 1
157+
else:
158+
y = ''
159+
return y
160+
[builtins fixtures/isinstance.py]
161+
162+
[case testIsinstanceAndTypeVarValues4]
163+
from typing import typevar, Undefined
164+
T = typevar('T', values=(int, str))
165+
def f(x: T) -> T:
166+
if isinstance(x, int):
167+
y = 1
168+
else:
169+
y = object()
170+
return y # E: Incompatible return value type
171+
[builtins fixtures/isinstance.py]
172+
[out]
173+
main: In function "f":
174+
175+
[case testIsinstanceAndTypeVarValues5]
176+
from typing import typevar, Undefined
177+
T = typevar('T', values=(int, str))
178+
def f(x: T) -> T:
179+
if isinstance(x, int):
180+
y = object()
181+
else:
182+
y = ''
183+
return y # E: Incompatible return value type
184+
[builtins fixtures/isinstance.py]
185+
[out]
186+
main: In function "f":
187+
151188
[case testTypeVarValuesAndNestedCalls]
152189
from typing import typevar
153190
T = typevar('T', values=(int, str))

0 commit comments

Comments
 (0)