Repository: python/mypy

Issue:
AssertionError: All arguments must be fully typed
* Are you reporting a bug, or opening a feature request? **bug**
* Please insert below the code you are checking with mypy,
  or a mock-up repro if the source is private. We would appreciate
  if you try to simplify your case to a minimal repro.

```
from dataclasses import dataclass

@dataclass(frozen=True)
class Modifiers:
    pass

@dataclass(frozen=True)
class Buff:
    modifiers: Modifiers

@dataclass(frozen=True)
class HB(Buff):
    modifiers = Modifiers()
```

* What is the actual behavior/output?

```
bug.py:11: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.701
Traceback (most recent call last):
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/bin/mypy", line 10, in <module>
    sys.exit(console_entry())
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/__main__.py", line 7, in console_entry
    main(None)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/main.py", line 84, in main
    res = build.build(sources, options, None, flush_errors, fscache)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/build.py", line 163, in build
    result = _build(sources, options, alt_lib_path, flush_errors, fscache)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/build.py", line 218, in _build
    graph = dispatch(sources, manager)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/build.py", line 2461, in dispatch
    process_graph(graph, manager)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/build.py", line 2761, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/build.py", line 2862, in process_stale_scc
    graph[id].semantic_analysis()
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/build.py", line 1997, in semantic_analysis
    self.manager.semantic_analyzer.visit_file(self.tree, self.xpath, self.options, patches)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/semanal.py", line 309, in visit_file
    self.accept(d)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/semanal.py", line 3791, in accept
    node.accept(self)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/nodes.py", line 896, in accept
    return visitor.visit_class_def(self)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/semanal.py", line 807, in visit_class_def
    self.analyze_class(defn)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/semanal.py", line 825, in analyze_class
    self.analyze_class_body_common(defn)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/semanal.py", line 833, in analyze_class_body_common
    self.apply_class_plugin_hooks(defn)
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/semanal.py", line 895, in apply_class_plugin_hooks
    hook(ClassDefContext(defn, decorator, self))
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/plugins/dataclasses.py", line 330, in dataclass_class_maker_callback
    transformer.transform()
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/plugins/dataclasses.py", line 100, in transform
    return_type=NoneTyp(),
  File "/Users/ezyang/Dev/oss/dl-hmc-calc-env/lib/python3.7/site-packages/mypy/plugins/common.py", line 97, in add_method
    assert arg.type_annotation, 'All arguments must be fully typed.'
AssertionError: All arguments must be fully typed.
bug.py:11: : note: use --pdb to drop into pdb
```

* What is the behavior/output you expect?

No crash

* What are the versions of mypy and Python you are using?

```
(/Users/ezyang/Dev/oss/dl-hmc-calc-env) MacBook-Pro-116:dl-hmc-calc ezyang$ python --version
Python 3.7.3
(/Users/ezyang/Dev/oss/dl-hmc-calc-env) MacBook-Pro-116:dl-hmc-calc ezyang$ mypy --version
mypy 0.701
```

*  Do you see the same issue after installing mypy from Git master?

I didn't try.

* What are the mypy flags you are using? (For example --strict-optional)

None


Discussion:
Thanks for reporting! This is quite bad crash, also it is interesting that it also crashes with a different traceback if one uses `--new-semantic-analyzer`:
```python-traceback
Traceback (most recent call last):
  File "/home/ivan/mypy_dev/bin/mypy", line 11, in <module>
    load_entry_point('mypy==0.710+dev.9c74efd4e04b0485444eed6a9d61c86046b8195f', 'console_scripts', 'mypy')()
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/__main__.py", line 7, in console_entry
    main(None)
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/main.py", line 85, in main
    res = build.build(sources, options, None, flush_errors, fscache)
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/build.py", line 164, in build
    result = _build(sources, options, alt_lib_path, flush_errors, fscache)
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/build.py", line 220, in _build
    graph = dispatch(sources, manager)
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/build.py", line 2490, in dispatch
    process_graph(graph, manager)
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/build.py", line 2802, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/build.py", line 2900, in process_stale_scc
    semantic_analysis_for_scc(graph, scc, manager.errors)
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/newsemanal/semanal_main.py", line 73, in semantic_analysis_for_scc
    process_top_levels(graph, scc, patches)
  File "/home/ivan/mypy_dev/lib/python3.6/site-packages/mypy/newsemanal/semanal_main.py", line 172, in process_top_levels
    assert not all_deferred, 'Must not defer during final iteration'
AssertionError: Must not defer during final iteration
```
Hi,

I'm able to reproduce this with master branch (300c846a244a99e0c9cd9ade6b0400c4142a0f77), the output is a bit different from the previously posted (same example code as @ezyang):

```
$ mypy --show-traceback repro.py                         
repro.py:12: error: INTERNAL ERROR -- Please try using mypy master on Github:
https://mypy.rtfd.io/en/latest/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 0.770+dev.300c846a244a99e0c9cd9ade6b0400c4142a0f77
Traceback (most recent call last):
  File "/Users/kristofferb/Library/Caches/pypoetry/virtualenvs/mypy-dataclass-pUk8QsQY-py3.7/bin/mypy", line 11, in <module>
    load_entry_point('mypy', 'console_scripts', 'mypy')()
  File "/Users/kristofferb/Code/rand/mypy/mypy/__main__.py", line 8, in console_entry
    main(None, sys.stdout, sys.stderr)
  File "/Users/kristofferb/Code/rand/mypy/mypy/main.py", line 89, in main
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/Users/kristofferb/Code/rand/mypy/mypy/build.py", line 167, in build
    sources, options, alt_lib_path, flush_errors, fscache, stdout, stderr, extra_plugins
  File "/Users/kristofferb/Code/rand/mypy/mypy/build.py", line 235, in _build
    graph = dispatch(sources, manager, stdout)
  File "/Users/kristofferb/Code/rand/mypy/mypy/build.py", line 2611, in dispatch
    process_graph(graph, manager)
  File "/Users/kristofferb/Code/rand/mypy/mypy/build.py", line 2918, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/kristofferb/Code/rand/mypy/mypy/build.py", line 3011, in process_stale_scc
    mypy.semanal_main.semantic_analysis_for_scc(graph, scc, manager.errors)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal_main.py", line 77, in semantic_analysis_for_scc
    process_top_levels(graph, scc, patches)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal_main.py", line 202, in process_top_levels
    patches)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal_main.py", line 330, in semantic_analyze_target
    active_type=active_type)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal.py", line 378, in refresh_partial
    self.refresh_top_level(node)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal.py", line 389, in refresh_top_level
    self.accept(d)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal.py", line 4695, in accept
    node.accept(self)
  File "/Users/kristofferb/Code/rand/mypy/mypy/nodes.py", line 939, in accept
    return visitor.visit_class_def(self)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal.py", line 1029, in visit_class_def
    self.analyze_class(defn)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal.py", line 1106, in analyze_class
    self.analyze_class_body_common(defn)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal.py", line 1115, in analyze_class_body_common
    self.apply_class_plugin_hooks(defn)
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal.py", line 1161, in apply_class_plugin_hooks
    hook(ClassDefContext(defn, decorator, self))
  File "/Users/kristofferb/Code/rand/mypy/mypy/plugins/dataclasses.py", line 383, in dataclass_class_maker_callback
    transformer.transform()
  File "/Users/kristofferb/Code/rand/mypy/mypy/plugins/dataclasses.py", line 90, in transform
    ctx.api.defer()
  File "/Users/kristofferb/Code/rand/mypy/mypy/semanal.py", line 4429, in defer
    assert not self.final_iteration, 'Must not defer during final iteration'
AssertionError: Must not defer during final iteration
repro.py:12: : note: use --pdb to drop into pdb
```
Probably we want to produce an error here, since the assignment `HB` doesn't accomplish anything?

Resolving patch:
diff --git a/mypy/plugins/common.py b/mypy/plugins/common.py
--- a/mypy/plugins/common.py
+++ b/mypy/plugins/common.py
@@ -1,15 +1,18 @@
-from typing import List, Optional
+from typing import List, Optional, Union
 
 from mypy.nodes import (
     ARG_POS, MDEF, Argument, Block, CallExpr, Expression, SYMBOL_FUNCBASE_TYPES,
-    FuncDef, PassStmt, RefExpr, SymbolTableNode, Var
+    FuncDef, PassStmt, RefExpr, SymbolTableNode, Var, JsonDict,
 )
-from mypy.plugin import ClassDefContext
+from mypy.plugin import ClassDefContext, SemanticAnalyzerPluginInterface
 from mypy.semanal import set_callable_name
-from mypy.types import CallableType, Overloaded, Type, TypeVarDef, get_proper_type
+from mypy.types import (
+    CallableType, Overloaded, Type, TypeVarDef, deserialize_type, get_proper_type,
+)
 from mypy.typevars import fill_typevars
 from mypy.util import get_unique_redefinition_name
 from mypy.typeops import try_getting_str_literals  # noqa: F401  # Part of public API
+from mypy.fixup import TypeFixer
 
 
 def _get_decorator_bool_argument(
@@ -128,3 +131,11 @@ def add_method(
 
     info.names[name] = SymbolTableNode(MDEF, func, plugin_generated=True)
     info.defn.defs.body.append(func)
+
+
+def deserialize_and_fixup_type(
+    data: Union[str, JsonDict], api: SemanticAnalyzerPluginInterface
+) -> Type:
+    typ = deserialize_type(data)
+    typ.accept(TypeFixer(api.modules, allow_missing=False))
+    return typ
diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py
--- a/mypy/plugins/dataclasses.py
+++ b/mypy/plugins/dataclasses.py
@@ -5,12 +5,14 @@
 
 from mypy.nodes import (
     ARG_OPT, ARG_POS, MDEF, Argument, AssignmentStmt, CallExpr,
-    Context, Expression, FuncDef, JsonDict, NameExpr, RefExpr,
+    Context, Expression, JsonDict, NameExpr, RefExpr,
     SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr, PlaceholderNode
 )
-from mypy.plugin import ClassDefContext
-from mypy.plugins.common import add_method, _get_decorator_bool_argument
-from mypy.types import Instance, NoneType, TypeVarDef, TypeVarType, get_proper_type
+from mypy.plugin import ClassDefContext, SemanticAnalyzerPluginInterface
+from mypy.plugins.common import (
+    add_method, _get_decorator_bool_argument, deserialize_and_fixup_type,
+)
+from mypy.types import Type, Instance, NoneType, TypeVarDef, TypeVarType, get_proper_type
 from mypy.server.trigger import make_wildcard_trigger
 
 # The set of decorators that generate dataclasses.
@@ -31,6 +33,7 @@ def __init__(
             has_default: bool,
             line: int,
             column: int,
+            type: Optional[Type],
     ) -> None:
         self.name = name
         self.is_in_init = is_in_init
@@ -38,19 +41,21 @@ def __init__(
         self.has_default = has_default
         self.line = line
         self.column = column
+        self.type = type
 
-    def to_argument(self, info: TypeInfo) -> Argument:
+    def to_argument(self) -> Argument:
         return Argument(
-            variable=self.to_var(info),
-            type_annotation=info[self.name].type,
+            variable=self.to_var(),
+            type_annotation=self.type,
             initializer=None,
             kind=ARG_OPT if self.has_default else ARG_POS,
         )
 
-    def to_var(self, info: TypeInfo) -> Var:
-        return Var(self.name, info[self.name].type)
+    def to_var(self) -> Var:
+        return Var(self.name, self.type)
 
     def serialize(self) -> JsonDict:
+        assert self.type
         return {
             'name': self.name,
             'is_in_init': self.is_in_init,
@@ -58,11 +63,16 @@ def serialize(self) -> JsonDict:
             'has_default': self.has_default,
             'line': self.line,
             'column': self.column,
+            'type': self.type.serialize(),
         }
 
     @classmethod
-    def deserialize(cls, info: TypeInfo, data: JsonDict) -> 'DataclassAttribute':
-        return cls(**data)
+    def deserialize(
+        cls, info: TypeInfo, data: JsonDict, api: SemanticAnalyzerPluginInterface
+    ) -> 'DataclassAttribute':
+        data = data.copy()
+        typ = deserialize_and_fixup_type(data.pop('type'), api)
+        return cls(type=typ, **data)
 
 
 class DataclassTransformer:
@@ -81,12 +91,7 @@ def transform(self) -> None:
             # Some definitions are not ready, defer() should be already called.
             return
         for attr in attributes:
-            node = info.get(attr.name)
-            if node is None:
-                # Nodes of superclass InitVars not used in __init__ cannot be reached.
-                assert attr.is_init_var and not attr.is_in_init
-                continue
-            if node.type is None:
+            if attr.type is None:
                 ctx.api.defer()
                 return
         decorator_arguments = {
@@ -106,7 +111,7 @@ def transform(self) -> None:
             add_method(
                 ctx,
                 '__init__',
-                args=[attr.to_argument(info) for attr in attributes if attr.is_in_init],
+                args=[attr.to_argument() for attr in attributes if attr.is_in_init],
                 return_type=NoneType(),
             )
 
@@ -191,7 +196,7 @@ def reset_init_only_vars(self, info: TypeInfo, attributes: List[DataclassAttribu
                     del info.names[attr.name]
                 else:
                     # Nodes of superclass InitVars not used in __init__ cannot be reached.
-                    assert attr.is_init_var and not attr.is_in_init
+                    assert attr.is_init_var
                 for stmt in info.defn.defs.body:
                     if isinstance(stmt, AssignmentStmt) and stmt.unanalyzed_type:
                         lvalue = stmt.lvalues[0]
@@ -282,6 +287,7 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
                 has_default=has_default,
                 line=stmt.line,
                 column=stmt.column,
+                type=sym.type,
             ))
 
         # Next, collect attributes belonging to any class in the MRO
@@ -301,23 +307,7 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
             for data in info.metadata['dataclass']['attributes']:
                 name = data['name']  # type: str
                 if name not in known_attrs:
-                    attr = DataclassAttribute.deserialize(info, data)
-                    if attr.is_init_var:
-                        # InitVars are removed from classes so, in order for them to be inherited
-                        # properly, we need to re-inject them into subclasses' sym tables here.
-                        # To do that, we look 'em up from the parents' __init__.  These variables
-                        # are subsequently removed from the sym table at the end of
-                        # DataclassTransformer.transform.
-                        superclass_init = info.get_method('__init__')
-                        if isinstance(superclass_init, FuncDef):
-                            attr_node = _get_arg_from_init(superclass_init, attr.name)
-                            if attr_node is None:
-                                # Continue the loop: we will look it up in the next MRO entry.
-                                # Don't add it to the known or super attrs because we don't know
-                                # anything about it yet
-                                continue
-                            else:
-                                cls.info.names[attr.name] = attr_node
+                    attr = DataclassAttribute.deserialize(info, data, ctx.api)
                     known_attrs.add(name)
                     super_attrs.append(attr)
                 elif all_attrs:
@@ -365,21 +355,13 @@ def _freeze(self, attributes: List[DataclassAttribute]) -> None:
                 assert isinstance(var, Var)
                 var.is_property = True
             else:
-                var = attr.to_var(info)
+                var = attr.to_var()
                 var.info = info
                 var.is_property = True
                 var._fullname = info.fullname + '.' + var.name
                 info.names[var.name] = SymbolTableNode(MDEF, var)
 
 
-def _get_arg_from_init(init_method: FuncDef, attr_name: str) -> Optional[SymbolTableNode]:
-    """Given an init method and an attribute name, find the Var in the init method's args."""
-    for arg, arg_name in zip(init_method.arguments, init_method.arg_names):
-        if arg_name == attr_name:
-            return SymbolTableNode(MDEF, arg.variable)
-    return None
-
-
 def dataclass_class_maker_callback(ctx: ClassDefContext) -> None:
     """Hooks into the class typechecking process to add support for dataclasses.
     """


Test patch:
diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test
--- a/test-data/unit/check-attr.test
+++ b/test-data/unit/check-attr.test
@@ -1244,3 +1244,18 @@ class A2:
     b: int = attr.ib()
 
 [builtins fixtures/list.pyi]
+
+[case testAttrsInheritanceNoAnnotation]
+import attr
+
+@attr.s
+class A:
+    foo = attr.ib()  # type: int
+
+x = 0
+@attr.s
+class B(A):
+    foo = x
+
+reveal_type(B)  # N: Revealed type is 'def (foo: builtins.int) -> __main__.B'
+[builtins fixtures/bool.pyi]
diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test
--- a/test-data/unit/check-dataclasses.test
+++ b/test-data/unit/check-dataclasses.test
@@ -723,6 +723,51 @@ C(1, 'a')  # E: Argument 2 to "C" has incompatible type "str"; expected "int"
 
 [builtins fixtures/primitives.pyi]
 
+[case testDataclassesInitVarIncremental]
+import a
+
+[file a.py]
+import dataclasses
+from b import A
+
+@dataclasses.dataclass
+class B(A):
+    b: int = dataclasses.field(init=False)
+
+    def __post_init__(self, a: int) -> None:
+        super().__post_init__(a)
+        self.b = a + 1
+
+[file a.py.2]
+import dataclasses
+from b import A
+
+@dataclasses.dataclass
+class B(A):
+    b: int = dataclasses.field(init=False)
+
+    def __post_init__(self, a: int) -> None:
+        super().__post_init__(a)
+        self.b = a + 2
+
+reveal_type(B)
+
+[file b.py]
+import dataclasses
+
+@dataclasses.dataclass
+class A:
+    a: dataclasses.InitVar[int]
+    _a: int = dataclasses.field(init=False)
+
+    def __post_init__(self, a: int) -> None:
+        self._a = a
+[out2]
+tmp/a.py:12: note: Revealed type is 'def (a: builtins.int) -> a.B'
+
+[builtins fixtures/primitives.pyi]
+
+
 [case testNoComplainFieldNone]
 # flags: --python-version 3.6
 # flags: --no-strict-optional
@@ -957,3 +1002,33 @@ class A:  # E: Name 'x' already defined (possibly by an import)
 @dataclass
 class B(A):
     pass
+
+[case testDataclassInheritanceNoAnnotation]
+from dataclasses import dataclass
+
+@dataclass
+class A:
+    foo: int
+
+x = 0
+@dataclass
+class B(A):
+    foo = x
+
+reveal_type(B)  # N: Revealed type is 'def (foo: builtins.int) -> __main__.B'
+
+[case testDataclassInheritanceNoAnnotation2]
+from dataclasses import dataclass
+
+@dataclass(frozen=True)
+class A:
+    foo: int
+
+@dataclass
+class B(A):
+    @property
+    def foo(self) -> int: pass  # E: Signature of "foo" incompatible with supertype "A"
+
+reveal_type(B)  # N: Revealed type is 'def (foo: builtins.int) -> __main__.B'
+
+[builtins fixtures/property.pyi]