Skip to content

Several dataclass crashes involving Final attributes #10090

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
matthewhughes934 opened this issue Feb 13, 2021 · 5 comments · Fixed by #13528
Closed

Several dataclass crashes involving Final attributes #10090

matthewhughes934 opened this issue Feb 13, 2021 · 5 comments · Fixed by #13528

Comments

@matthewhughes934
Copy link
Contributor

Crash Report

I was just trying things out and found a crash with:

from dataclasses import dataclass
from typing import Final

@dataclass
class FirstClass:
    FIRST_CONST: Final = 3

@dataclass  # mypy runs fine if this isn't a dataclass
class SecondClass:
    SECOND_CONST: Final = FirstClass.FIRST_CONST

Note: I don't think this code is very usable. I think I would want ClassVar here (or just a module-scoped variable), but thought the report might be interesting all the same.

Traceback

Traceback on current master:

Please report a bug at https://github.com/python/mypy/issues
version: 0.820+dev.88dde657fedecf17e15222ad4b685b0aeddcc423
Traceback (most recent call last):
  File "/home/mjh/.pyenv/versions/3.8.6/bin/mypy", line 33, in <module>
    sys.exit(load_entry_point('mypy', 'console_scripts', 'mypy')())
  File "/home/mjh/src/mypy/mypy/__main__.py", line 11, in console_entry
    main(None, sys.stdout, sys.stderr)
  File "/home/mjh/src/mypy/mypy/main.py", line 98, in main
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/home/mjh/src/mypy/mypy/build.py", line 179, in build
    result = _build(
  File "/home/mjh/src/mypy/mypy/build.py", line 253, in _build
    graph = dispatch(sources, manager, stdout)
  File "/home/mjh/src/mypy/mypy/build.py", line 2658, in dispatch
    process_graph(graph, manager)
  File "/home/mjh/src/mypy/mypy/build.py", line 2982, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/home/mjh/src/mypy/mypy/build.py", line 3074, in process_stale_scc
    mypy.semanal_main.semantic_analysis_for_scc(graph, scc, manager.errors)
  File "/home/mjh/src/mypy/mypy/semanal_main.py", line 78, in semantic_analysis_for_scc
    process_top_levels(graph, scc, patches)
  File "/home/mjh/src/mypy/mypy/semanal_main.py", line 199, in process_top_levels
    deferred, incomplete, progress = semantic_analyze_target(next_id, state,
  File "/home/mjh/src/mypy/mypy/semanal_main.py", line 326, in semantic_analyze_target
    analyzer.refresh_partial(refresh_node,
  File "/home/mjh/src/mypy/mypy/semanal.py", line 394, in refresh_partial
    self.refresh_top_level(node)
  File "/home/mjh/src/mypy/mypy/semanal.py", line 405, in refresh_top_level
    self.accept(d)
  File "/home/mjh/src/mypy/mypy/semanal.py", line 4835, in accept
    node.accept(self)
  File "/home/mjh/src/mypy/mypy/nodes.py", line 950, in accept
    return visitor.visit_class_def(self)
  File "/home/mjh/src/mypy/mypy/semanal.py", line 1048, in visit_class_def
    self.analyze_class(defn)
  File "/home/mjh/src/mypy/mypy/semanal.py", line 1125, in analyze_class
    self.analyze_class_body_common(defn)
  File "/home/mjh/src/mypy/mypy/semanal.py", line 1134, in analyze_class_body_common
    self.apply_class_plugin_hooks(defn)
  File "/home/mjh/src/mypy/mypy/semanal.py", line 1180, in apply_class_plugin_hooks
    hook(ClassDefContext(defn, decorator, self))
  File "/home/mjh/src/mypy/mypy/plugins/dataclasses.py", line 361, in dataclass_class_maker_callback
    transformer.transform()
  File "/home/mjh/src/mypy/mypy/plugins/dataclasses.py", line 106, in transform
    ctx.api.defer()
  File "/home/mjh/src/mypy/mypy/semanal.py", line 4554, in defer
    assert not self.final_iteration, 'Must not defer during final iteration'
AssertionError: Must not defer during final iteration
/home/mjh/tmp/testing_py/mypy_test.py:9: : note: use --pdb to drop into pdb

Traceback on pip package:

mypy_test.py:9: 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.800
Traceback (most recent call last):
  File "mypy/semanal.py", line 4835, in accept
  File "mypy/nodes.py", line 950, in accept
  File "mypy/semanal.py", line 1048, in visit_class_def
  File "mypy/semanal.py", line 1125, in analyze_class
  File "mypy/semanal.py", line 1134, in analyze_class_body_common
  File "mypy/semanal.py", line 1180, in apply_class_plugin_hooks
  File "mypy/plugins/dataclasses.py", line 361, in dataclass_class_maker_callback
  File "mypy/plugins/dataclasses.py", line 106, in transform
  File "mypy/semanal.py", line 4554, in defer
AssertionError: Must not defer during final iteration
mypy_test.py:9: : note: use --pdb to drop into pdb

To Reproduce

Run mypy over a file containing the content above.

Your Environment

  • Mypy version used: 0.820+dev.88dde657fedecf17e15222ad4b685b0aeddcc423 and 0.800
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.8.6
  • Operating system and version: Debian GNU/Linux 10 (buster)
@sisp
Copy link

sisp commented Jun 22, 2021

The same problem occurs for this snippet:

from dataclasses import dataclass
from typing import Final


@dataclass
class A:
    x: Final = "a"


@dataclass  # Removing this decorator makes it work
class B:
    y: Final = A()
$ mypy dataclass_final_test.py --show-traceback
dataclass_final_test.py:11: error: INTERNAL ERROR -- Please try using mypy master on Github:
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 0.902
Traceback (most recent call last):
  File "mypy/semanal.py", line 4872, in accept
  File "mypy/nodes.py", line 950, in accept
  File "mypy/semanal.py", line 1056, in visit_class_def
  File "mypy/semanal.py", line 1134, in analyze_class
  File "mypy/semanal.py", line 1143, in analyze_class_body_common
  File "mypy/semanal.py", line 1189, in apply_class_plugin_hooks
  File "mypy/plugins/dataclasses.py", line 384, in dataclass_class_maker_callback
  File "mypy/plugins/dataclasses.py", line 109, in transform
  File "mypy/semanal.py", line 4583, in defer
AssertionError: Must not defer during final iteration
dataclass_final_test.py:11: : note: use --pdb to drop into pdb

@sisp
Copy link

sisp commented Jun 23, 2021

Another occurrence of this problem with just a single dataclass:

from dataclasses import dataclass
from typing import Final


def f():
    @dataclass
    class A:
        x: Final = "a"
$ mypy --show-traceback dataclass_final_test.py 
dataclass_final_test.py:7: error: INTERNAL ERROR -- Please try using mypy master on Github:
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 0.910
Traceback (most recent call last):
  File "mypy/semanal.py", line 4872, in accept
  File "mypy/nodes.py", line 950, in accept
  File "mypy/semanal.py", line 1056, in visit_class_def
  File "mypy/semanal.py", line 1134, in analyze_class
  File "mypy/semanal.py", line 1143, in analyze_class_body_common
  File "mypy/semanal.py", line 1189, in apply_class_plugin_hooks
  File "mypy/plugins/dataclasses.py", line 384, in dataclass_class_maker_callback
  File "mypy/plugins/dataclasses.py", line 109, in transform
  File "mypy/semanal.py", line 4583, in defer
AssertionError: Must not defer during final iteration
dataclass_final_test.py:7: : note: use --pdb to drop into pdb

@hauntsaninja hauntsaninja changed the title INTERNAL ERROR on dataclasses sharing 'Final' attribute Several dataclass crashes involving Final attributes Sep 6, 2021
@SyntaxColoring
Copy link
Contributor

SyntaxColoring commented Dec 4, 2021

Another variant:

from dataclasses import dataclass
from http import HTTPStatus
from typing import Final

@dataclass
class MyResponse:
    status_code: Final = HTTPStatus.NOT_FOUND
sketch_dataclasses.py:6: error: INTERNAL ERROR -- Please try using mypy master on Github:
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 0.910
Traceback (most recent call last):
  File "mypy/semanal.py", line 4872, in accept
  File "mypy/nodes.py", line 950, in accept
  File "mypy/semanal.py", line 1056, in visit_class_def
  File "mypy/semanal.py", line 1134, in analyze_class
  File "mypy/semanal.py", line 1143, in analyze_class_body_common
  File "mypy/semanal.py", line 1189, in apply_class_plugin_hooks
  File "mypy/plugins/dataclasses.py", line 384, in dataclass_class_maker_callback
  File "mypy/plugins/dataclasses.py", line 109, in transform
  File "mypy/semanal.py", line 4583, in defer
AssertionError: Must not defer during final iteration
sketch_dataclasses.py:6: : note: use --pdb to drop into pdb

@AlexWaygood
Copy link
Member

This still crashes on master, but the traceback is now different following #12762. Running mypy on the original repro now produces:

(venv) C:\Users\alexw\coding\mypy>mypy test.py
Traceback (most recent call last):
  File "C:\Users\alexw\coding\mypy\venv\Scripts\mypy-script.py", line 33, in <module>
    sys.exit(load_entry_point('mypy', 'console_scripts', 'mypy')())
  File "c:\users\alexw\coding\mypy\mypy\__main__.py", line 12, in console_entry
    main(None, sys.stdout, sys.stderr)
  File "c:\users\alexw\coding\mypy\mypy\main.py", line 96, in main
    res, messages, blockers = run_build(sources, options, fscache, t0, stdout, stderr)
  File "c:\users\alexw\coding\mypy\mypy\main.py", line 173, in run_build
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "c:\users\alexw\coding\mypy\mypy\build.py", line 181, in build
    result = _build(
  File "c:\users\alexw\coding\mypy\mypy\build.py", line 257, in _build
    graph = dispatch(sources, manager, stdout)
  File "c:\users\alexw\coding\mypy\mypy\build.py", line 2755, in dispatch
    process_graph(graph, manager)
  File "c:\users\alexw\coding\mypy\mypy\build.py", line 3113, in process_graph
    process_stale_scc(graph, scc, manager)
  File "c:\users\alexw\coding\mypy\mypy\build.py", line 3205, in process_stale_scc
    mypy.semanal_main.semantic_analysis_for_scc(graph, scc, manager.errors)
  File "c:\users\alexw\coding\mypy\mypy\semanal_main.py", line 88, in semantic_analysis_for_scc
    apply_class_plugin_hooks(graph, scc, errors)
  File "c:\users\alexw\coding\mypy\mypy\semanal_main.py", line 405, in apply_class_plugin_hooks
    assert num_passes < 10, "Internal error: too many class plugin hook passes"
AssertionError: Internal error: too many class plugin hook passes

@AlexWaygood
Copy link
Member

Yet another repro for this crash was identified by @DetachHead in #13377, which I just closed as a duplicate of this issue:

from dataclasses import dataclass, field
from typing import Final

@dataclass
class Foo:
    a: Final = field(default=1)

ilevkivskyi added a commit that referenced this issue Aug 27, 2022
Fixes #10090 

Unfortunately we cannot fully support this use case. Mypy requires explicit type annotations to generate methods for dataclasses before type checking. While type inference for bare `Final` happens during type checking. I still try to infer type if the default is a literal, otherwise give an error, and use `Any` for generated methods.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants