[red-knot] Clarify behavior when redeclaring base class attributes (#15826)
Some checks are pending
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions

# Summary

Clarify the behavior regarding re-declaration of attributes from base
classes following [this
discussion](https://github.com/astral-sh/ruff/pull/15808#discussion_r1934236095)
This commit is contained in:
David Peter 2025-01-30 14:49:23 +01:00 committed by GitHub
parent 13cf3e65f1
commit 451f251a31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -324,20 +324,35 @@ reveal_type(c_instance.variable_with_class_default1) # revealed: str
class Base:
declared_in_body: int | None = 1
can_not_be_redeclared: str | None = None
base_class_attribute_1: str | None
base_class_attribute_2: str | None
base_class_attribute_3: str | None
def __init__(self) -> None:
self.defined_in_init: str | None = "value in base"
class Intermediate(Base):
# TODO: Mypy does not report an error here, but pyright does:
# "… overrides symbol of same name in class "Base". Variable is mutable so its type is invariant"
# We should introduce a diagnostic for this. Whether or not that should be enabled by default can
# still be discussed.
can_not_be_redeclared: str = "a"
# Re-declaring base class attributes with the *same *type is fine:
base_class_attribute_1: str | None = None
def __init__(self) -> None:
super().__init__()
# Re-declaring them with a *narrower type* is unsound, because modifications
# through a `Base` reference could violate that constraint.
#
# Mypy does not report an error here, but pyright does: "… overrides symbol
# of same name in class "Base". Variable is mutable so its type is invariant"
#
# We should introduce a diagnostic for this. Whether or not that should be
# enabled by default can still be discussed.
#
# TODO: This should be an error
base_class_attribute_2: str
# Re-declaring attributes with a *wider type* directly violates LSP.
#
# In this case, both mypy and pyright report an error.
#
# TODO: This should be an error
base_class_attribute_3: str | int | None
class Derived(Intermediate): ...