Skip to content

Support recursive NamedTuple #9397

Closed
Closed
@habilain

Description

@habilain

🐛 Bug Report

NamedTuple's appear to behave in unexpected ways with recursion, especially when compared to frozen dataclasses (which are rather similar, as far as the user is concerned).

To Reproduce

from __future__ import annotations
from typing import NamedTuple, Optional

class A(NamedTuple):
  a: Optional[A]

Produces a "mypy-sample1.py:5: error: Cannot resolve name "A" (possible cyclic definition)". However,

from __future__ import annotations
from typing import Optional
from dataclasses import dataclass

@dataclass(frozen=True)
class A:
  a: Optional[A]

Passes MyPy just fine, and as far as a user is concerned, presents a very similar surface for MyPy to type check (i.e. both have a read-only attribute a which is either None or of class A).

Expected Behavior

The expected behaviour would be that both NamedTuple and frozen dataclass behave the same, as NamedTuple and frozen dataclasses present logically similar behaviour with regards to the attribute 'a'.

Actual Behavior

In addition to the odd behaviour with cycle checker triggering on NamedTuple but not on dataclasses, it's possible to fool the cycle checker completely and have MyPy crash by recursing too far (e.g. issue #8695 and although that issue has been reported with a recursive type that could never be instantiated, I've encountered the same behaviour with type definitions that can be instantiated, but not in a minimal example friendly format). I think this specific behaviour is the root cause, as the real problem is that for some reason NamedTuple's are behaving differently to what would be expected.

Your Environment

  • Mypy version used: mypy 0.782
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.8.2
  • Operating system and version: Linux

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions