Closed
Description
from typing import NamedTuple, Union
class Person(NamedTuple):
name: Union[str, "NamePair"]
class NamePair(NamedTuple):
first: str
last: str
print(Person(name=NamePair(first="John", last="Doe")))
# Person(name=NamePair(first='John', last='Doe'))
Works fine in Python 3.6, but in mypy:
mypy_breaks.py:10: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.521
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/bin/mypy", line 11, in <module>
sys.exit(console_entry())
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/__main__.py", line 7, in console_entry
main(None)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/main.py", line 50, in main
res = type_check_only(sources, bin_dir, options)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/main.py", line 97, in type_check_only
options=options)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/build.py", line 196, in build
graph = dispatch(sources, manager)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/build.py", line 1801, in dispatch
process_graph(graph, manager)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/build.py", line 2044, in process_graph
process_stale_scc(graph, scc, manager)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/build.py", line 2147, in process_stale_scc
graph[id].type_check_first_pass()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/build.py", line 1716, in type_check_first_pass
self.type_checker.check_first_pass()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checker.py", line 185, in check_first_pass
self.accept(d)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
stmt.accept(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/nodes.py", line 829, in accept
return visitor.visit_expression_stmt(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checker.py", line 1883, in visit_expression_stmt
self.expr_checker.accept(s.expr, allow_none_return=True, always_allow_any=True)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 2209, in accept
typ = self.visit_call_expr(node, allow_none_return=True)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 247, in visit_call_expr
ret_type = self.check_call_expr_with_callee_type(callee_type, e, fullname, object_type)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 459, in check_call_expr_with_callee_type
object_type=object_type)[0]
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 519, in check_call
callee, args, arg_kinds, formal_to_actual)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 675, in infer_arg_types_in_context2
res[ai] = self.accept(args[ai], callee.arg_types[i])
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 2213, in accept
typ = node.accept(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/nodes.py", line 1307, in accept
return visitor.visit_call_expr(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 215, in visit_call_expr
callee_type = self.accept(e.callee, always_allow_any=True)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 2213, in accept
typ = node.accept(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/nodes.py", line 1219, in accept
return visitor.visit_name_expr(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 128, in visit_name_expr
result = self.analyze_ref_expr(e)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkexpr.py", line 156, in analyze_ref_expr
result = type_object_type(node, self.named_type)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkmember.py", line 525, in type_object_type
return type_object_type_from_function(init_method, info, fallback)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkmember.py", line 530, in type_object_type_from_function
signature = bind_self(function_type(init_or_new, fallback))
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkmember.py", line 664, in bind_self
arg_types = [expand(x) for x in func.arg_types[1:]]
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkmember.py", line 664, in <listcomp>
arg_types = [expand(x) for x in func.arg_types[1:]]
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/checkmember.py", line 662, in expand
return expand_type(target, {func.variables[0].id: typearg})
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/expandtype.py", line 16, in expand_type
return typ.accept(ExpandTypeVisitor(env))
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/types.py", line 1114, in accept
return visitor.visit_union_type(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/expandtype.py", line 117, in visit_union_type
return UnionType.make_simplified_union(self.expand_types(t.items), t.line, t.column)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/types.py", line 1096, in make_simplified_union
if (i != j and is_proper_subtype(tj, ti)):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/subtypes.py", line 569, in is_proper_subtype
return left.accept(ProperSubtypeVisitor(right))
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/types.py", line 435, in accept
return visitor.visit_instance(self)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mypy/subtypes.py", line 605, in visit_instance
for base in left.type.mro:
TypeError: 'NoneType' object is not iterable
Interestingly not an issue if I break the forward-reference
from typing import NamedTuple, Union
class NamePair(NamedTuple):
first: str
last: str
class Person(NamedTuple):
name: Union[str, "NamePair"]
print(Person(name=NamePair(first="John", last="Doe"))) # mypy works fine
or if I switch to using classes
from typing import NamedTuple, Union
class Person(NamedTuple):
name: Union[str, "NamePair"]
class NamePair:
def __init__(self, first: str, last: str) -> None:
self.first = first
self.last = last
print(Person(name=NamePair(first="John", last="Doe"))) # mypy works fine
or if I drop the union typing
from typing import NamedTuple, Union
class Person(NamedTuple):
name: "NamePair"
class NamePair(NamedTuple):
first: str
last: str
print(Person(name=NamePair(first="John", last="Doe"))) # mypy works fine
including by using Optional
from typing import NamedTuple, Optional
class Person(NamedTuple):
name: Optional["NamePair"]
class NamePair(NamedTuple):
first: str
last: str
print(Person(name=NamePair(first="John", last="Doe"))) # mypy works fine
Activity
emmatyping commentedon Sep 23, 2017
NamedTuples and forward references can be problematic. See eg #3952 fixes a lot of these cases. I'm not sure if this case will be solved by that particular PR however.
ilevkivskyi commentedon Sep 23, 2017
Yes, this will be fixed by #3952, I updated the PR description, will also now add this example to the tests.
Add one more test as suggested in python#3990
ilevkivskyi commentedon Sep 23, 2017
OK, added, thanks for the idea for an additional test! If everything will be fine then this PR will be merged before the next release that will happen very soon.
Fix crashes and fails in forward references (#3952)