Skip to content

multiple init=False dataclasses with an __init__ that has a different signature crashes mypy #8209

Closed

Description

@beckjake

In the presence of init=False dataclass subclassing chains and particular __init__ overrides, the semantic analyzer gets stuck in a loop and crashes - apparently because it can't make forward progress. I don't really understand what's going on here even after spending some time in pdb, but I've got it down to what I think is a pretty minimal (and silly) test case.

Please provide more information to help us understand the issue:

  • Are you reporting a bug, or opening a feature request?

A 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, InitVar

@dataclass
class A:
    a: InitVar[bool]
    def __post_init__(self, a: bool):
        pass

@dataclass
class B(A):
    b: InitVar[bool]
    def __post_init__(self, a: bool, b: bool):
        super().__post_init__(a=a)

@dataclass(init=False)
class C(B):
    def __init__(self, a: bool, b: bool) -> None:
        super().__init__(a=a, b=b)

@dataclass(init=False)
class D(C):
    def __init__(self, a: bool) -> None:
        super().__init__(a, False)
  • What is the actual behavior/output?
    Mypy crashes with a big deferral trace indicating that it got stuck on line 22 (D.__init__)

  • What is the behavior/output you expect?

No crashes!

  • What are the versions of mypy and Python you are using?
    Do you see the same issue after installing mypy from Git master?

Python 3.6.5/3.8.0
Mypy from git master (9101707)

  • What are the mypy flags you are using? (For example --strict-optional)
    None
  • If mypy crashed with a traceback, please paste
    the full traceback below.

No traceback, but here is a deferral trace:

Deferral trace:
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
    maybe_crash:22
maybe_crash.py: error: INTERNAL ERROR: maximum semantic analysis iteration count reached
Found 1 error in 1 file (checked 1 source file)

Activity

  1. beckjake commented on Dec 28, 2019

    @beckjake
    ContributorAuthor

    After some playing around with this, I believe it's because C.__init__ defines an a: bool of its own, and that is discovered by the MRO lookup, but something about it being an InitVar attr makes the type field of the attribute None, which triggers an endless series of defer() calls in DataclassTransformer.transform. I suppose the fix is to change _get_arg_from_init to look for InitVar declarations only, or something? It's not clear to me why the type is missing from C.__init__.

  2. georgeaf99 commented on Jan 10, 2020

    @georgeaf99

    Bump, I'm also seeing this error with attrs, not dataclass

  3. beckjake commented on Jan 10, 2020

    @beckjake
    ContributorAuthor

    I made a tiny bit of progress on this, but I got stuck (pasting from gitter):

    When a function defintion has been found in ASTConverter.do_func_def, I see that my method in question (in this case, C.__init__) has a func_type of def (self: Any, a: bool?, b: bool?) -> None?. But the args list, all variables (a.variable) have a type field of None. I think this is the data that ends up getting stored for C.__init__, and causes the dataclass transformer to get confused.

    It wasn't clear to me why that type info wasn't added.

  4. JukkaL commented on Jan 13, 2020

    @JukkaL
    Collaborator

    This crash seems pretty bad. It has been around at least since 0.730, so at least it's not a (recent) regression.

  5. JukkaL commented on Feb 14, 2020

    @JukkaL
    Collaborator

    The crash was fixed by #8271.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions