Repository: python/mypy

Issue:
Internal error with dataclasses.InitVar and init=False
I was trying to work around #4997 by adding a dummy field to a dataclass which would not appear in `__init__` (so `init=False`) or in `fields()` (so `InitVar`), but ran into a mypy crash when subclassing it.

Whilst the workaround is a nasty hack, it works at runtime, so IMO mypy should cope with it.

test.py:

```python
import dataclasses


@dataclasses.dataclass
class Struct:
    _dummy: dataclasses.InitVar = dataclasses.field(init=False)


@dataclasses.dataclass
class Header(Struct):
    foo: int
```

mypy output:

```pytb
$ ~/src/mypy/venv/bin/mypy test.py --show-traceback
test.py:10: 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.730+dev.c610a312853921d09083f7525c183810e4232056
Traceback (most recent call last):
  File "/home/josh/src/mypy/venv/bin/mypy", line 10, in <module>
    sys.exit(console_entry())
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/__main__.py", line 8, in console_entry
    main(None, sys.stdout, sys.stderr)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/main.py", line 83, in main
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/build.py", line 162, in build
    result = _build(sources, options, alt_lib_path, flush_errors, fscache, stdout, stderr)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/build.py", line 224, in _build
    graph = dispatch(sources, manager, stdout)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/build.py", line 2559, in dispatch
    process_graph(graph, manager)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/build.py", line 2868, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/build.py", line 2961, in process_stale_scc
    semantic_analysis_for_scc(graph, scc, manager.errors)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal_main.py", line 77, in semantic_analysis_for_scc
    process_top_levels(graph, scc, patches)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal_main.py", line 202, in process_top_levels
    patches)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal_main.py", line 330, in semantic_analyze_target
    active_type=active_type)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal.py", line 376, in refresh_partial
    self.refresh_top_level(node)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal.py", line 387, in refresh_top_level
    self.accept(d)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal.py", line 4591, in accept
    node.accept(self)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/nodes.py", line 925, in accept
    return visitor.visit_class_def(self)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal.py", line 1011, in visit_class_def
    self.analyze_class(defn)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal.py", line 1082, in analyze_class
    self.analyze_class_body_common(defn)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal.py", line 1091, in analyze_class_body_common
    self.apply_class_plugin_hooks(defn)
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/semanal.py", line 1136, in apply_class_plugin_hooks
    hook(ClassDefContext(defn, decorator, self))
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/plugins/dataclasses.py", line 352, in dataclass_class_maker_callback
    transformer.transform()
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/plugins/dataclasses.py", line 84, in transform
    if info[attr.name].type is None:
  File "/home/josh/src/mypy/venv/lib/python3.7/site-packages/mypy/nodes.py", line 2428, in __getitem__
    raise KeyError(name)
KeyError: '_dummy'
test.py:10: : note: use --pdb to drop into pdb
```


Discussion:
Thanks for reporting! I confirm this crash on master.

Resolving patch:
diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py
--- a/mypy/plugins/dataclasses.py
+++ b/mypy/plugins/dataclasses.py
@@ -83,7 +83,12 @@ def transform(self) -> None:
             # Some definitions are not ready, defer() should be already called.
             return
         for attr in attributes:
-            if info[attr.name].type is None:
+            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:
                 ctx.api.defer()
                 return
         decorator_arguments = {
@@ -184,7 +189,11 @@ def reset_init_only_vars(self, info: TypeInfo, attributes: List[DataclassAttribu
         """Remove init-only vars from the class and reset init var declarations."""
         for attr in attributes:
             if attr.is_init_var:
-                del info.names[attr.name]
+                if attr.name in info.names:
+                    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
                 for stmt in info.defn.defs.body:
                     if isinstance(stmt, AssignmentStmt) and stmt.unanalyzed_type:
                         lvalue = stmt.lvalues[0]


Test patch:
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
@@ -555,6 +555,22 @@ app.database_name  # E: "Application" has no attribute "database_name"
 class Yes: ...
 [builtins fixtures/list.pyi]
 
+[case testDataclassesNoInitInitVarInheritance]
+from dataclasses import dataclass, field, InitVar
+
+@dataclass
+class Super:
+    foo: InitVar = field(init=False)
+
+@dataclass
+class Sub(Super):
+    bar: int
+
+sub = Sub(5)
+sub.foo  # E: "Sub" has no attribute "foo"
+sub.bar
+[builtins fixtures/bool.pyi]
+
 [case testDataclassFactory]
 from typing import Type, TypeVar
 from dataclasses import dataclass