Repository: python/mypy

Issue:
Assertion error on loading .mypy_cache data
Hi. I see an assertion when run mypy on cached data.
`rm -rf .mypy_cache` or `incremental = False` helps but working support for cached data would be nice.
The assertion happens not always but after a relative big source code change (`isort` + `black` run).

Sorry, I cannot provide a code for the problem reproducion (it is a private closed source probject).
Error traceback is applied.
```
Traceback (most recent call last):
  File "/home/andrew/.virtualenvs/platform-api-clients/bin/mypy", line 11, in <module>
    sys.exit(console_entry())
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/__main__.py", line 7, in console_entry
    main(None)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/main.py", line 92, in main
    res = build.build(sources, options, None, flush_errors, fscache)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/build.py", line 156, in build
    result = _build(sources, options, alt_lib_path, flush_errors, fscache)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/build.py", line 206, in _build
    graph = dispatch(sources, manager)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/build.py", line 2232, in dispatch
    process_graph(graph, manager)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/build.py", line 2525, in process_graph
    process_fresh_modules(graph, prev_scc, manager)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/build.py", line 2609, in process_fresh_modules
    graph[id].load_tree()
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/build.py", line 1604, in load_tree
    self.tree = MypyFile.deserialize(data)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/nodes.py", line 277, in deserialize
    tree.names = SymbolTable.deserialize(data['names'])
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/nodes.py", line 2864, in deserialize
    st[key] = SymbolTableNode.deserialize(value)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/nodes.py", line 2812, in deserialize
    node = SymbolNode.deserialize(data['node'])
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/nodes.py", line 200, in deserialize
    return method(data)
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/nodes.py", line 478, in deserialize
    for d in data['items']])
  File "/home/andrew/.virtualenvs/platform-api-clients/lib/python3.6/site-packages/mypy/nodes.py", line 446, in __init__
    assert len(items) > 0
AssertionError
```



Discussion:
Thanks for reporting!

It seems to me this assert can be simply removed, there is a comment few lines below saying that empty items `# This may happen for malformed overload`.

Are you using `@singledispatch` or custom property decorators?
Yes, the project uses `@singledispatch`.
It can explain why I have no such errors on other projects

Resolving patch:
diff --git a/mypy/nodes.py b/mypy/nodes.py
--- a/mypy/nodes.py
+++ b/mypy/nodes.py
@@ -443,11 +443,11 @@ class OverloadedFuncDef(FuncBase, SymbolNode, Statement):
 
     def __init__(self, items: List['OverloadPart']) -> None:
         super().__init__()
-        assert len(items) > 0
         self.items = items
         self.unanalyzed_items = items.copy()
         self.impl = None
-        self.set_line(items[0].line)
+        if len(items) > 0:
+            self.set_line(items[0].line)
         self.is_final = False
 
     def name(self) -> str:
@@ -478,6 +478,9 @@ def deserialize(cls, data: JsonDict) -> 'OverloadedFuncDef':
             for d in data['items']])
         if data.get('impl') is not None:
             res.impl = cast(OverloadPart, SymbolNode.deserialize(data['impl']))
+            # set line for empty overload items, as not set in __init__
+            if len(res.items) > 0:
+                res.set_line(res.impl.line)
         if data.get('type') is not None:
             res.type = mypy.types.deserialize_type(data['type'])
         res._fullname = data['fullname']


Test patch: