Skip to content

Commit 451f251

Browse files
authored
[red-knot] Clarify behavior when redeclaring base class attributes (#15826)
# Summary Clarify the behavior regarding re-declaration of attributes from base classes following [this discussion](#15808 (comment))
1 parent 13cf3e6 commit 451f251

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

crates/red_knot_python_semantic/resources/mdtest/attributes.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -324,20 +324,35 @@ reveal_type(c_instance.variable_with_class_default1) # revealed: str
324324
class Base:
325325
declared_in_body: int | None = 1
326326

327-
can_not_be_redeclared: str | None = None
327+
base_class_attribute_1: str | None
328+
base_class_attribute_2: str | None
329+
base_class_attribute_3: str | None
328330

329331
def __init__(self) -> None:
330332
self.defined_in_init: str | None = "value in base"
331333

332334
class Intermediate(Base):
333-
# TODO: Mypy does not report an error here, but pyright does:
334-
# "… overrides symbol of same name in class "Base". Variable is mutable so its type is invariant"
335-
# We should introduce a diagnostic for this. Whether or not that should be enabled by default can
336-
# still be discussed.
337-
can_not_be_redeclared: str = "a"
338-
339-
def __init__(self) -> None:
340-
super().__init__()
335+
# Re-declaring base class attributes with the *same *type is fine:
336+
base_class_attribute_1: str | None = None
337+
338+
# Re-declaring them with a *narrower type* is unsound, because modifications
339+
# through a `Base` reference could violate that constraint.
340+
#
341+
# Mypy does not report an error here, but pyright does: "… overrides symbol
342+
# of same name in class "Base". Variable is mutable so its type is invariant"
343+
#
344+
# We should introduce a diagnostic for this. Whether or not that should be
345+
# enabled by default can still be discussed.
346+
#
347+
# TODO: This should be an error
348+
base_class_attribute_2: str
349+
350+
# Re-declaring attributes with a *wider type* directly violates LSP.
351+
#
352+
# In this case, both mypy and pyright report an error.
353+
#
354+
# TODO: This should be an error
355+
base_class_attribute_3: str | int | None
341356

342357
class Derived(Intermediate): ...
343358

0 commit comments

Comments
 (0)