@@ -324,20 +324,35 @@ reveal_type(c_instance.variable_with_class_default1) # revealed: str
324
324
class Base :
325
325
declared_in_body: int | None = 1
326
326
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
328
330
329
331
def __init__ (self ) -> None :
330
332
self .defined_in_init: str | None = " value in base"
331
333
332
334
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
341
356
342
357
class Derived (Intermediate ): ...
343
358
0 commit comments