Skip to content

[ty] Do not consider a subclass of a @dataclass_transform-decorated class to have dataclass-like semantics if it has type in its MRO#24679

Merged
AlexWaygood merged 1 commit into
mainfrom
alex-carl/dataclass_transform
Apr 16, 2026
Merged

[ty] Do not consider a subclass of a @dataclass_transform-decorated class to have dataclass-like semantics if it has type in its MRO#24679
AlexWaygood merged 1 commit into
mainfrom
alex-carl/dataclass_transform

Conversation

@AlexWaygood
Copy link
Copy Markdown
Member

Summary

Currently we consider both subclasses of RegistryMeta and instances of RegistryMeta to have dataclass-like semantics in the following snippet:

from typing import dataclass_transform

@dataclass_transform()
class RegistryMeta(type): ...

class SubclassOf(RegistryMeta):
    x: str

class InstanceOf(metaclass=RegistryMeta):
    x: str

reveal_type(SubclassOf.__init__)  # `(self: SubclassOf, x: str) -> None`
reveal_type(InstanceOf.__init__)  # `(self: InstanceOf, x: str) -> None`

According to a strict reading of the spec, this is the correct behaviour:

If dataclass_transform is applied to a class, dataclass-like semantics will be assumed for any class that directly or indirectly derives from the decorated class or uses the decorated class as a metaclass.

However, the practical effect of this would be that SubclassOf is no longer usable as a metaclass -- and since it is an instance of type, that's probably how the user actually wants to use it! A class can only be soundly usable as a metaclass if it is callable with the same parameters as builtins.type -- but if having RegistryMeta in its MRO would lead to a new __init__ signature being synthesized for SubclassOf, SubclassOf will no longer be usable as a metaclass. That means that when we start checking the arguments implicit passed to metaclass constructors (as part of #24550), it will break the feature added in #24615 whereby classes that have SubclassOf as their metaclass would also be considered as having dataclass-like semantics.

This doesn't seem like desirable behaviour, so this PR adds a heuristic whereby if we see that a class inheriting from a @dataclass_transform-decorated class has type in its MRO, we will not bestow dataclass-like semantics onto that class; we will assume that the @dataclass_transform-decorated class only provides dataclass-like semantics to classes that have that class as their metaclass.

Test Plan

mdtests updated

Co-authored-by: Carl Meyer carl@astral.sh

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label Apr 16, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 16, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 87.94%. The percentage of expected errors that received a diagnostic held steady at 83.36%. The number of fully passing files held steady at 79/133.

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 16, 2026

Memory usage report

Summary

Project Old New Diff Outcome
prefect 716.28MB 716.79MB +0.07% (517.07kB)
sphinx 262.58MB 262.80MB +0.08% (224.58kB)
trio 117.56MB 117.66MB +0.08% (97.01kB)
flake8 47.91MB 47.94MB +0.05% (26.85kB)

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
code_generator_of_static_class 1.38MB 1.88MB +36.60% (517.07kB)

sphinx

Name Old New Diff Outcome
code_generator_of_static_class 519.54kB 744.09kB +43.22% (224.55kB)
StaticClassLiteral<'db>::is_typed_dict_ 183.24kB 183.26kB +0.01% (24.00B)

trio

Name Old New Diff Outcome
code_generator_of_static_class 212.65kB 309.66kB +45.62% (97.01kB)

flake8

Name Old New Diff Outcome
code_generator_of_static_class 61.57kB 88.41kB +43.61% (26.85kB)

@AlexWaygood AlexWaygood force-pushed the alex-carl/dataclass_transform branch from 02d9a7b to bc613cf Compare April 16, 2026 17:39
Person("Bob", email="bob@example.com", notes="other notes")
```

#### Inherited metaclass-based transformer
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we moved this test up, because it seemed to incorrectly be in the "Field specifiers using **kwargs" section, despite not having much to do with field specifiers that use **kwargs

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 16, 2026

ecosystem-analyzer results

No diagnostic changes detected ✅

Flaky changes detected. This PR summary excludes flaky changes; see the HTML report for details.

Full report with detailed diff (timing results)

@AlexWaygood AlexWaygood marked this pull request as ready for review April 16, 2026 17:46
… class to have dataclass-like semantics if it has `type` in its MRO
@AlexWaygood AlexWaygood force-pushed the alex-carl/dataclass_transform branch from bc613cf to 68ab287 Compare April 16, 2026 18:39
@AlexWaygood AlexWaygood merged commit c81782f into main Apr 16, 2026
56 checks passed
@AlexWaygood AlexWaygood deleted the alex-carl/dataclass_transform branch April 16, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants