Skip to content

Commit 458fb36

Browse files
authored
Fix slots issue with deferred base (#20573)
Fixes #17121 Generated by codex + hand simplification commit
1 parent 2e9243a commit 458fb36

2 files changed

Lines changed: 25 additions & 5 deletions

File tree

mypy/plugins/dataclasses.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -457,10 +457,9 @@ def add_slots(
457457
)
458458
return
459459

460-
generated_slots = {attr.name for attr in attributes}
461-
if (info.slots is not None and info.slots != generated_slots) or info.names.get(
462-
"__slots__"
463-
):
460+
existing_slots = info.names.get("__slots__")
461+
slots_defined_by_plugin = existing_slots is not None and existing_slots.plugin_generated
462+
if existing_slots is not None and not slots_defined_by_plugin:
464463
# This means we have a slots conflict.
465464
# Class explicitly specifies a different `__slots__` field.
466465
# And `@dataclass(slots=True)` is used.
@@ -478,14 +477,21 @@ def add_slots(
478477
# does not have concrete `__slots__` defined. Ignoring.
479478
return
480479

480+
generated_slots = {attr.name for attr in attributes}
481481
info.slots = generated_slots
482482

483483
# Now, insert `.__slots__` attribute to class namespace:
484484
slots_type = TupleType(
485485
[self._api.named_type("builtins.str") for _ in generated_slots],
486486
self._api.named_type("builtins.tuple"),
487487
)
488-
add_attribute_to_class(self._api, self._cls, "__slots__", slots_type)
488+
add_attribute_to_class(
489+
self._api,
490+
self._cls,
491+
"__slots__",
492+
slots_type,
493+
overwrite_existing=slots_defined_by_plugin,
494+
)
489495

490496
def reset_init_only_vars(self, info: TypeInfo, attributes: list[DataclassAttribute]) -> None:
491497
"""Remove init-only vars from the class and reset init var declarations."""

test-data/unit/check-dataclasses.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,20 @@ class PublishedMessages:
16061606
left: int
16071607
[builtins fixtures/dataclasses.pyi]
16081608

1609+
[case testDataclassSlotsWithDeferredBase]
1610+
# flags: --python-version 3.10
1611+
from dataclasses import dataclass
1612+
1613+
@dataclass
1614+
class A(B): ...
1615+
1616+
@dataclass
1617+
class B: ...
1618+
1619+
@dataclass(slots=True)
1620+
class C: ...
1621+
[builtins fixtures/dataclasses.pyi]
1622+
16091623
[case testDataclassesAnyInherit]
16101624
from dataclasses import dataclass
16111625
from typing import Any

0 commit comments

Comments
 (0)