Skip to content

Frozen dataclasses should have an implicit Final annotation on its members #20087

Closed as duplicate

Description

@alecov

Bug Report

Frozen dataclasses should be implicitly Final on its members.

Currently mypy detects correctly that a frozen dataclass member cannot be assigned to; this is similar (if not altogether equivalent) to having a Final annotation on that (and every) member. This is important because it affects type covariance:

To Reproduce

from typing import cast
from dataclasses import dataclass

class C: pass
class D(C): pass

@dataclass(frozen=True)
class MyData[T: C]:
    m: T

def f(x: MyData[C]) -> None: pass

f(cast(MyData[D], 0)) # error, T is invariant here because `m` is public and deemed assignable

However, since MyData above is frozen, m cannot be assigned to and can be deemed final for purposes of covariance.

Expected Behavior

The above should typecheck:

f(cast(MyData[D], 0)) # this should typecheck

Actual Behavior

The above doesn't typecheck.

Your Environment

  • Mypy version used: 1.18.2
  • Mypy command-line flags: nothing special
  • Mypy configuration options from mypy.ini (and other config files): strict mode = True
  • Python version used: 3.13.7

Activity

  1. alecov commented on Oct 18, 2025

    @alecov
    Author

    The current workaround is to use an explicit TypeVar with covariance=True in cases where covariance of this kind is desirable. There are no consequences other than having uglier code. Also, note that currently there is no way to explicitly annotate members as Final, because mypy does not accept typevars as arguments to Final.

  2. erictraut commented on Oct 19, 2025

    @erictraut

    This issue is discussed here. The invariance is due to the synthesized __replace__ method, which was introduced in Python 3.13.

  3. alecov commented on Oct 20, 2025

    @alecov
    Author

    Good, I think we can close this as a duplicate, then.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions