mirror of
https://github.com/astral-sh/ruff.git
synced 2026-05-06 08:56:57 -04:00
[ty] Detect invalid attribute overrides (#24767)
## Summary
We now detect Liskov violations when a parent-child pair have attributes
with a differing `ClassVar` status.
In general, we interpret an attribute without a `ClassVar` annotation as
an instance attribute, with the exception of cases like the following,
where we "allow" the child to "inherit" the annotation to adhere to the
conformance suite:
```python
class ProtoB(Protocol):
z: ClassVar[int]
class ProtoBImpl(ProtoB):
z = 0
```
There are a few other tricky cases to consider.
### Methods
Like Mypy and Pyright, we don't flag the following:
```py
from typing import Any, Callable, ClassVar
class Base:
f: ClassVar[Callable[..., Any]]
class Sub(Base):
def f(self) -> int:
return 1
```
### Descriptors
Like Mypy and Pyright, we don't flag the following:
```python
class Descriptor:
def __get__(self, obj: object, owner: type[object]) -> int:
return 1
class Base:
attr = Descriptor()
class Sub(Base):
attr: int
```
### Properties
Like Mypy and Pyright, we _do_ flag the following, since it changes the
class-vs.-instance contract:
```python
from typing import ClassVar
class Base:
attr: ClassVar[int]
class Sub(Base):
@property
def attr(self) -> int: # error: [invalid-attribute-override]
return 1
```
#### Final
We don't flag the following, because it already has a dedicated
diagnostic:
```python
from typing import Final
class Base:
attr: Final[int] = 1
class Sub(Base):
attr = 2 # error: [override-of-final-variable]
```
Closes https://github.com/astral-sh/ty/issues/3093.
This commit is contained in:
Generated
+150
-109
@@ -8,7 +8,7 @@
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.13">0.0.13</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22abstract-method-in-final-class%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2443" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2444" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class Derived(Base): # Error: `Derived` does not implement `method`
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20">0.0.1-alpha.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22ambiguous-protocol-member%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L660" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L661" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ class SubProto(BaseProto, Protocol):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.14">0.0.14</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22assert-type-unspellable-subtype%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2579" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2580" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ def _(x: int):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Preview (since <a href="https://github.com/astral-sh/ty/releases/tag/0.0.16">0.0.16</a>) ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22call-abstract-method%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2478" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2479" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ Foo.method() # Error: cannot call abstract classmethod
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22call-non-callable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L176" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L177" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ Calling a non-callable object will raise a `TypeError` at runtime.
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.7">0.0.7</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22call-top-callable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L194" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L195" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ def f(x: object):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22conflicting-argument-forms%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L245" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L246" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ f(int) # error
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22conflicting-declarations%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L271" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L272" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ a = 1
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22conflicting-metaclass%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L296" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L297" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -325,7 +325,7 @@ class C(A, B): ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22cyclic-class-definition%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L322" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L323" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -357,7 +357,7 @@ class B(A): ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.29">0.0.1-alpha.29</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22cyclic-type-alias-definition%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L348" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L349" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -385,7 +385,7 @@ type B = A
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.15">0.0.15</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22dataclass-field-order%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L466" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L467" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -417,7 +417,7 @@ class Example:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.16">0.0.1-alpha.16</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22deprecated%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L392" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L393" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -444,7 +444,7 @@ old_func() # emits [deprecated] diagnostic
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'ignore'."><code>ignore</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22division-by-zero%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L370" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L371" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -473,7 +473,7 @@ false positives it can produce.
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22duplicate-base%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L413" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L414" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -500,7 +500,7 @@ class B(A, A): ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.12">0.0.1-alpha.12</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22duplicate-kw-only%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L434" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L435" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -538,7 +538,7 @@ class A: # Crash at runtime
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.14">0.0.14</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22empty-body%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1008" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1009" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -609,7 +609,7 @@ def foo() -> "intt\b": ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.20">0.0.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22final-on-non-method%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2390" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2391" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -641,7 +641,7 @@ def my_function() -> int:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.15">0.0.15</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22final-without-value%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2416" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2417" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -736,7 +736,7 @@ def test(): -> "Literal[5]":
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22inconsistent-mro%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L777" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L778" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -766,7 +766,7 @@ class C(A, B): ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22index-out-of-bounds%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L801" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L802" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -792,7 +792,7 @@ t[3] # IndexError: tuple index out of range
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.33">0.0.1-alpha.33</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22ineffective-final%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2362" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2363" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -826,7 +826,7 @@ class MyClass: ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.12">0.0.1-alpha.12</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22instance-layout-conflict%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L549" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L550" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -915,7 +915,7 @@ an atypical memory layout.
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-argument-type%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L939" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L940" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -942,7 +942,7 @@ func("foo") # error: [invalid-argument-type]
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-assignment%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1048" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1049" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -970,7 +970,7 @@ a: int = ''
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-attribute-access%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2908" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2909" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -998,13 +998,54 @@ C().instance_var = 3 # okay
|
||||
C.instance_var = 3 # error: Cannot assign to instance variable
|
||||
```
|
||||
|
||||
## `invalid-attribute-override`
|
||||
|
||||
<small>
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.33">0.0.33</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-attribute-override%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3169" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
**What it does**
|
||||
|
||||
Detects attribute overrides that change whether an inherited attribute
|
||||
is a class variable or an instance variable.
|
||||
|
||||
This rule currently only covers class-variable and instance-variable
|
||||
category changes.
|
||||
|
||||
**Why is this bad?**
|
||||
|
||||
Pure class variables and instance variables have different access and
|
||||
assignment behavior. Overriding one with the other violates the
|
||||
[Liskov Substitution Principle] ("LSP"), because code that is valid for
|
||||
the superclass may no longer be valid for the subclass.
|
||||
|
||||
**Example**
|
||||
|
||||
```python
|
||||
from typing import ClassVar
|
||||
|
||||
class Base:
|
||||
instance_attr: int
|
||||
class_attr: ClassVar[int]
|
||||
|
||||
class Sub(Base):
|
||||
instance_attr: ClassVar[int] # error: [invalid-attribute-override]
|
||||
class_attr: int # error: [invalid-attribute-override]
|
||||
```
|
||||
|
||||
[Liskov Substitution Principle]: https://en.wikipedia.org/wiki/Liskov_substitution_principle
|
||||
|
||||
## `invalid-await`
|
||||
|
||||
<small>
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.19">0.0.1-alpha.19</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-await%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1070" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1071" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1040,7 +1081,7 @@ asyncio.run(main())
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-base%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1100" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1101" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1064,7 +1105,7 @@ class A(42): ... # error: [invalid-base]
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-context-manager%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1184" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1185" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1091,7 +1132,7 @@ with 1:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.12">0.0.12</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-dataclass%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L518" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L519" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1128,7 +1169,7 @@ class Foo(NamedTuple):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.13">0.0.13</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-dataclass-override%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L492" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L493" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1160,7 +1201,7 @@ class A:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-declaration%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1205" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1206" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1189,7 +1230,7 @@ a: str
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.20">0.0.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-enum-member-annotation%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1264" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1265" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1238,7 +1279,7 @@ class Pet(Enum):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-exception-caught%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1228" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1229" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1282,7 +1323,7 @@ except ZeroDivisionError:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.28">0.0.1-alpha.28</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-explicit-override%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2521" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2522" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1324,7 +1365,7 @@ class D(A):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.35">0.0.1-alpha.35</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-frozen-dataclass-subclass%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3266" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3302" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1368,7 +1409,7 @@ class NonFrozenChild(FrozenBase): # Error raised here
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-generic-class%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1348" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1349" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1406,7 +1447,7 @@ class D(Generic[U, T]): ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.12">0.0.12</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-generic-enum%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1306" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1307" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1485,7 +1526,7 @@ a = 20 / 0 # type: ignore
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.17">0.0.1-alpha.17</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-key%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L822" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L823" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1524,7 +1565,7 @@ carol = Person(name="Carol", aeg=25) # typo!
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.15">0.0.15</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-legacy-positional-parameter%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3344" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3380" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1585,7 +1626,7 @@ def f(x, y, /): # Python 3.8+ syntax
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-legacy-type-variable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1405" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1406" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1620,7 +1661,7 @@ def f(t: TypeVar("U")): ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.18">0.0.18</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-match-pattern%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1809" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1810" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1648,7 +1689,7 @@ match x:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-metaclass%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1533" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1534" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1682,7 +1723,7 @@ class B(metaclass=f): ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20">0.0.1-alpha.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-method-override%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3168" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3204" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1789,7 +1830,7 @@ Correct use of `@override` is enforced by ty's [`invalid-explicit-override`](#in
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.19">0.0.1-alpha.19</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-named-tuple%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L695" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L696" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1843,7 +1884,7 @@ AttributeError: Cannot overwrite NamedTuple attribute _asdict
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.31">0.0.31</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-named-tuple-override%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L743" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L744" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1884,7 +1925,7 @@ admin[0] # "Alice"
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.27">0.0.1-alpha.27</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-newtype%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1478" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1479" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1914,7 +1955,7 @@ Baz = NewType("Baz", int | str) # error: invalid base for `typing.NewType`
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-overload%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1560" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1561" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1964,7 +2005,7 @@ def foo(x: int) -> int: ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-parameter-default%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1659" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1660" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -1990,7 +2031,7 @@ def f(a: int = ''): ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-paramspec%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1433" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1434" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2021,7 +2062,7 @@ P2 = ParamSpec("S2") # error: ParamSpec name must match the variable it's assig
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-protocol%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L631" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L632" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2055,7 +2096,7 @@ TypeError: Protocols can only inherit from other protocols, got <class 'int'>
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-raise%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1679" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1680" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2104,7 +2145,7 @@ def g():
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-return-type%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L960" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L961" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2133,7 +2174,7 @@ def func() -> int:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-super-argument%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1722" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1723" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2229,7 +2270,7 @@ class C: ...
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.10">0.0.10</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-total-ordering%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3304" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3340" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2275,7 +2316,7 @@ class MyClass:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.6">0.0.1-alpha.6</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-alias-type%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1457" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1458" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2302,7 +2343,7 @@ NewAlias = TypeAliasType(get_name(), int) # error: TypeAliasType name mus
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.29">0.0.1-alpha.29</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-arguments%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2069" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2070" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2349,7 +2390,7 @@ Bar[int] # error: too few arguments
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-checking-constant%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1761" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1762" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2379,7 +2420,7 @@ TYPE_CHECKING = ''
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-form%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1785" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1786" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2409,7 +2450,7 @@ b: Annotated[int] # `Annotated` expects at least two arguments
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.11">0.0.1-alpha.11</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-guard-call%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1859" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1860" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2443,7 +2484,7 @@ f(10) # Error
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.11">0.0.1-alpha.11</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-guard-definition%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1831" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1832" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2477,7 +2518,7 @@ class C:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.15">0.0.15</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-variable-bound%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1928" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1929" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2508,7 +2549,7 @@ def g[U, T: U](): ... # error: [invalid-type-variable-bound]
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-variable-constraints%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1887" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1888" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2555,7 +2596,7 @@ U = TypeVar('U', list[int], int) # valid constrained Type
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.16">0.0.16</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-variable-default%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1953" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1954" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2587,7 +2628,7 @@ U = TypeVar("U", int, str, default=bytes) # error: [invalid-type-variable-defau
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.28">0.0.28</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-typed-dict-field%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3114" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3115" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2618,7 +2659,7 @@ class Child(Base):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.14">0.0.14</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-typed-dict-header%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3139" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3140" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2653,7 +2694,7 @@ def f(x: dict):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.9">0.0.9</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-typed-dict-statement%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3089" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3090" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2684,7 +2725,7 @@ class Foo(TypedDict):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.25">0.0.25</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-yield%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L983" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L984" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2715,7 +2756,7 @@ def gen() -> Iterator[int]:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.14">0.0.14</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22isinstance-against-protocol%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L855" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L856" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2770,7 +2811,7 @@ def h(arg2: type):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.15">0.0.15</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22isinstance-against-typed-dict%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L903" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L904" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2813,7 +2854,7 @@ def g(arg: object):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.30">0.0.30</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22mismatched-type-name%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1502" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1503" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2851,7 +2892,7 @@ Movie = TypedDict("Film", {"title": str}) # error: [mismatched-type-name]
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22missing-argument%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2009" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2010" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2876,7 +2917,7 @@ func() # TypeError: func() missing 1 required positional argument: 'x'
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20">0.0.1-alpha.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22missing-typed-dict-key%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3062" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3063" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2909,7 +2950,7 @@ alice["age"] # KeyError
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22no-matching-overload%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2028" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2029" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2938,7 +2979,7 @@ func("string") # error: [no-matching-overload]
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.30">0.0.30</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22non-callable-init-subclass%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1379" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1380" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2971,7 +3012,7 @@ class Sub(Super): ... # error: [non-callable-init-subclass]
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22not-iterable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2110" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2111" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -2997,7 +3038,7 @@ for i in 34: # TypeError: 'int' object is not iterable
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22not-subscriptable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2051" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2052" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3021,7 +3062,7 @@ Subscripting an object that does not support it will raise a `TypeError` at runt
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.29">0.0.1-alpha.29</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22override-of-final-method%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2308" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2309" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3054,7 +3095,7 @@ class B(A):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.16">0.0.16</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22override-of-final-variable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2335" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2336" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3087,7 +3128,7 @@ class B(A):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22parameter-already-assigned%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2161" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2162" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3114,7 +3155,7 @@ f(1, x=2) # Error raised here
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22positional-only-parameter-as-kwarg%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2735" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2736" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3141,7 +3182,7 @@ f(x=1) # Error raised here
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'ignore'."><code>ignore</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-missing-attribute%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2182" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2183" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3174,7 +3215,7 @@ A.c # AttributeError: type object 'A' has no attribute 'c'
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-missing-implicit-call%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L219" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L220" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3206,7 +3247,7 @@ A()[0] # TypeError: 'A' object is not subscriptable
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'ignore'."><code>ignore</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-missing-import%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2229" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2230" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3243,7 +3284,7 @@ from module import a # ImportError: cannot import name 'a' from 'module'
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.23">0.0.23</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-missing-submodule%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2208" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2209" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3270,7 +3311,7 @@ html.parser # AttributeError: module 'html' has no attribute 'parser'
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'ignore'."><code>ignore</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-unresolved-reference%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2259" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2260" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3334,7 +3375,7 @@ def test(): -> "int":
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22redundant-cast%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2936" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2937" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3361,7 +3402,7 @@ cast(int, f()) # Redundant
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.18">0.0.18</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22redundant-final-classvar%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2957" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2958" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3393,7 +3434,7 @@ class C:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.20">0.0.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22shadowed-type-variable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2983" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2984" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3427,7 +3468,7 @@ class Outer[T]:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22static-assert-error%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2884" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2885" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3457,7 +3498,7 @@ static_assert(int(2.0 * 3.0) == 6) # error: does not have a statically known tr
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22subclass-of-final-class%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2285" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2286" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3486,7 +3527,7 @@ class B(A): ... # Error raised here
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.30">0.0.1-alpha.30</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22super-call-in-named-tuple-method%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2669" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2670" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3520,7 +3561,7 @@ class F(NamedTuple):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22too-many-positional-arguments%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2609" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2610" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3547,7 +3588,7 @@ f("foo") # Error raised here
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22type-assertion-failure%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2557" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2558" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3575,7 +3616,7 @@ def _(x: int):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unavailable-implicit-super-arguments%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2630" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2631" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3621,7 +3662,7 @@ class A:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.20">0.0.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unbound-type-variable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1979" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1980" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3658,7 +3699,7 @@ class C(Generic[T]):
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22undefined-reveal%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2696" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2697" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3682,7 +3723,7 @@ reveal_type(1) # NameError: name 'reveal_type' is not defined
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unknown-argument%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2714" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2715" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3709,7 +3750,7 @@ f(x=1, y=2) # Error raised here
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unresolved-attribute%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2756" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2757" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3737,7 +3778,7 @@ A().foo # AttributeError: 'A' object has no attribute 'foo'
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.15">0.0.1-alpha.15</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unresolved-global%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3010" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3011" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3795,7 +3836,7 @@ def g():
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unresolved-import%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2778" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2779" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3820,7 +3861,7 @@ import foo # ModuleNotFoundError: No module named 'foo'
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unresolved-reference%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2797" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2798" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3845,7 +3886,7 @@ print(x) # NameError: name 'x' is not defined
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.7">0.0.1-alpha.7</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unsupported-base%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1118" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1119" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3884,7 +3925,7 @@ class D(C): ... # error: [unsupported-base]
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unsupported-bool-conversion%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2130" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2131" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3921,7 +3962,7 @@ b1 < b2 < b1 # exception raised here
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'ignore'."><code>ignore</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.12">0.0.12</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unsupported-dynamic-base%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1151" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1152" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3961,7 +4002,7 @@ def factory(base: type[Base]) -> type:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unsupported-operator%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2816" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2817" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -3989,7 +4030,7 @@ A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Preview (since <a href="https://github.com/astral-sh/ty/releases/tag/0.0.21">0.0.21</a>) ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unused-awaitable%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2838" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2839" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -4095,7 +4136,7 @@ to `false`.
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22useless-overload-body%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1603" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1604" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
@@ -4158,7 +4199,7 @@ def foo(x: int | str) -> int | str:
|
||||
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22zero-stepsize-in-slice%22" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2865" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2866" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
||||
@@ -362,6 +362,251 @@ class Sub23(Super4):
|
||||
def method(self, x, *args, y, **kwargs): ...
|
||||
```
|
||||
|
||||
## `ClassVar` and instance variables
|
||||
|
||||
A pure class variable cannot override an inherited instance variable, and an instance variable
|
||||
cannot override an inherited pure class variable.
|
||||
|
||||
### Direct overrides
|
||||
|
||||
An annotation without `ClassVar` declares an instance variable, even if the declaration also has a
|
||||
class-level default value. An explicit `ClassVar` declaration is a pure class variable. Overriding
|
||||
one with the other changes the places where the attribute is valid, so it violates Liskov
|
||||
substitution:
|
||||
|
||||
```py
|
||||
from typing import ClassVar
|
||||
|
||||
class Base:
|
||||
instance_attr: int
|
||||
instance_attr_with_default: int = 1
|
||||
class_attr: ClassVar[int] = 1
|
||||
|
||||
class Subclass(Base):
|
||||
# error: [invalid-attribute-override] "class variable cannot override instance variable `Base.instance_attr`"
|
||||
instance_attr: ClassVar[int]
|
||||
|
||||
# error: [invalid-attribute-override] "class variable cannot override instance variable `Base.instance_attr_with_default`"
|
||||
instance_attr_with_default: ClassVar[int] = 1
|
||||
|
||||
# error: [invalid-attribute-override] "instance variable cannot override class variable `Base.class_attr`"
|
||||
class_attr: int
|
||||
|
||||
class ValidSubclass(Base):
|
||||
instance_attr: int
|
||||
instance_attr_with_default: int = 1
|
||||
class_attr: ClassVar[int] = 1
|
||||
```
|
||||
|
||||
### Regular class-body assignments
|
||||
|
||||
An unannotated class-body assignment is an instance variable with a class-level default. This means
|
||||
it can replace another inherited instance-variable default. If it overrides an inherited `ClassVar`,
|
||||
it inherits that declaration and remains a class variable. However, an explicit `ClassVar` cannot
|
||||
override an inherited unannotated class-body assignment, because code using the base class can still
|
||||
write that attribute through an instance:
|
||||
|
||||
```py
|
||||
from typing import ClassVar
|
||||
|
||||
class Base:
|
||||
instance_attr_with_default: int = 1
|
||||
class_attr: ClassVar[int] = 1
|
||||
|
||||
class RegularClassAttributeOverride(Base):
|
||||
class_attr = 1
|
||||
|
||||
class AugmentedClassAttributeOverride(Base):
|
||||
class_attr = 1
|
||||
class_attr += 1
|
||||
|
||||
class IntermediateClassAttributeOverride(Base):
|
||||
class_attr = 1
|
||||
|
||||
class ExplicitClassVarOverrideAfterInheritedClassVar(IntermediateClassAttributeOverride):
|
||||
class_attr: ClassVar[int] = 1
|
||||
|
||||
class RegularClassAttributeBase:
|
||||
attr = 1
|
||||
|
||||
class ExplicitClassVarOverride(RegularClassAttributeBase):
|
||||
# error: [invalid-attribute-override] "class variable cannot override instance variable `RegularClassAttributeBase.attr`"
|
||||
attr: ClassVar[int] = 1
|
||||
|
||||
class ClassDefaultBase:
|
||||
class_default: int = 1
|
||||
declared_instance: bool
|
||||
|
||||
class ClassDefaultSubclass(ClassDefaultBase):
|
||||
class_default = 2
|
||||
declared_instance = True
|
||||
```
|
||||
|
||||
### Method definitions
|
||||
|
||||
Method definitions create descriptors in the class body. They are not instance variable
|
||||
declarations, so the class-variable vs. instance-variable override check does not apply to them:
|
||||
|
||||
```py
|
||||
from collections.abc import Callable
|
||||
from typing import Any, ClassVar
|
||||
|
||||
class ClassVarBase:
|
||||
plain: ClassVar[Callable[..., Any]]
|
||||
static: ClassVar[Callable[..., Any]]
|
||||
class_: ClassVar[Callable[..., Any]]
|
||||
non_callable: ClassVar[int]
|
||||
|
||||
class MethodSubclass(ClassVarBase):
|
||||
def plain(self, x: int) -> int:
|
||||
return x
|
||||
|
||||
@staticmethod
|
||||
def static(x: int) -> int:
|
||||
return x
|
||||
|
||||
@classmethod
|
||||
def class_(cls, x: int) -> int:
|
||||
return x
|
||||
|
||||
def non_callable(self) -> int:
|
||||
return 1
|
||||
|
||||
class PropertyBase:
|
||||
attr: ClassVar[int]
|
||||
|
||||
class PropertySubclass(PropertyBase):
|
||||
@property
|
||||
def attr( # error: [invalid-attribute-override] "instance variable cannot override class variable `PropertyBase.attr`"
|
||||
self,
|
||||
) -> int:
|
||||
return 1
|
||||
```
|
||||
|
||||
### Repeated inherited conflicts
|
||||
|
||||
If a parent class already made an invalid change from class variable to instance variable, a child
|
||||
that keeps the parent's kind should not receive a duplicate diagnostic. The same applies in the
|
||||
other direction:
|
||||
|
||||
```py
|
||||
from typing import ClassVar
|
||||
|
||||
class GrandparentClassVar:
|
||||
attr: ClassVar[int]
|
||||
|
||||
class ParentInstance(GrandparentClassVar):
|
||||
# error: [invalid-attribute-override] "instance variable cannot override class variable `GrandparentClassVar.attr`"
|
||||
attr: int
|
||||
|
||||
class ChildInstance(ParentInstance):
|
||||
attr: int
|
||||
|
||||
class GrandparentInstance:
|
||||
attr: int
|
||||
|
||||
class ParentClassVar(GrandparentInstance):
|
||||
# error: [invalid-attribute-override] "class variable cannot override instance variable `GrandparentInstance.attr`"
|
||||
attr: ClassVar[int]
|
||||
|
||||
class ChildClassVar(ParentClassVar):
|
||||
attr: ClassVar[int]
|
||||
```
|
||||
|
||||
### Descriptors
|
||||
|
||||
A descriptor can define different behavior when accessed on an instance. Because descriptor lookup
|
||||
is neither a pure class variable nor a normal instance variable, overriding it with an instance
|
||||
attribute is accepted:
|
||||
|
||||
```py
|
||||
from typing import ClassVar
|
||||
|
||||
class Descriptor:
|
||||
def __get__(self, instance: object, owner: type[object]) -> int:
|
||||
return 1
|
||||
|
||||
class DescriptorBase:
|
||||
descriptor_attr = Descriptor()
|
||||
|
||||
class DescriptorOverride(DescriptorBase):
|
||||
descriptor_attr: int
|
||||
|
||||
class DescriptorAnnotationBase:
|
||||
descriptor_attr: Descriptor
|
||||
|
||||
class DescriptorAnnotationOverride(DescriptorAnnotationBase):
|
||||
# error: [invalid-attribute-override] "class variable cannot override instance variable `DescriptorAnnotationBase.descriptor_attr`"
|
||||
descriptor_attr: ClassVar[Descriptor]
|
||||
```
|
||||
|
||||
### Multiple inheritance
|
||||
|
||||
The subclass must satisfy every base class. It is not enough for the first base in the MRO to agree
|
||||
with the subclass: an unrelated base that declares the same member as a pure class variable still
|
||||
makes an instance-variable override invalid.
|
||||
|
||||
```py
|
||||
from typing import ClassVar
|
||||
|
||||
class ClassVarBase:
|
||||
attr: ClassVar[int]
|
||||
|
||||
class InstanceBase:
|
||||
attr: int
|
||||
|
||||
class MultipleInheritanceSubclass(InstanceBase, ClassVarBase):
|
||||
# error: [invalid-attribute-override] "instance variable cannot override class variable `ClassVarBase.attr`"
|
||||
attr: int
|
||||
```
|
||||
|
||||
### Dataclasses
|
||||
|
||||
Dataclass fields are instance variables, even though they are usually declared in the class body.
|
||||
`ClassVar` fields remain pure class variables and are excluded from dataclass instance fields:
|
||||
|
||||
```py
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar
|
||||
|
||||
@dataclass
|
||||
class DC6:
|
||||
x: int
|
||||
y: ClassVar[int] = 1
|
||||
|
||||
@dataclass
|
||||
class DC7(DC6):
|
||||
# error: [invalid-attribute-override] "class variable cannot override instance variable `DC6.x`"
|
||||
x: ClassVar[int]
|
||||
|
||||
# error: [invalid-attribute-override] "instance variable cannot override class variable `DC6.y`"
|
||||
y: int
|
||||
```
|
||||
|
||||
### Protocol implementations
|
||||
|
||||
Regular class-body assignments can implement protocol instance attributes. The `ClassVar` case below
|
||||
uses the same rule as normal classes: an unannotated class-body assignment over an inherited
|
||||
`ClassVar` provides a value while preserving the inherited declaration.
|
||||
|
||||
```py
|
||||
from typing import ClassVar, Protocol
|
||||
|
||||
class ProtocolBase(Protocol):
|
||||
class_attr: ClassVar[int]
|
||||
instance_attr: int
|
||||
instance_attr_with_default: int = 1
|
||||
|
||||
class ProtocolImpl(ProtocolBase):
|
||||
class_attr = 1
|
||||
instance_attr = 1
|
||||
instance_attr_with_default = 1
|
||||
|
||||
class ProtocolWithClassVarImpl(ProtocolBase):
|
||||
class_attr = 0
|
||||
instance_attr = 0
|
||||
```
|
||||
|
||||
## The entire class hierarchy is checked
|
||||
|
||||
If a child class's method definition is Liskov-compatible with the method definition on its parent
|
||||
|
||||
@@ -159,6 +159,7 @@ pub(crate) fn register_lints(registry: &mut LintRegistryBuilder) {
|
||||
registry.register_lint(&INVALID_TYPED_DICT_STATEMENT);
|
||||
registry.register_lint(&INVALID_TYPED_DICT_FIELD);
|
||||
registry.register_lint(&INVALID_TYPED_DICT_HEADER);
|
||||
registry.register_lint(&INVALID_ATTRIBUTE_OVERRIDE);
|
||||
registry.register_lint(&INVALID_METHOD_OVERRIDE);
|
||||
registry.register_lint(&INVALID_EXPLICIT_OVERRIDE);
|
||||
registry.register_lint(&SUPER_CALL_IN_NAMED_TUPLE_METHOD);
|
||||
@@ -3165,6 +3166,41 @@ declare_lint! {
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// ## What it does
|
||||
/// Detects attribute overrides that change whether an inherited attribute
|
||||
/// is a class variable or an instance variable.
|
||||
///
|
||||
/// This rule currently only covers class-variable and instance-variable
|
||||
/// category changes.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Pure class variables and instance variables have different access and
|
||||
/// assignment behavior. Overriding one with the other violates the
|
||||
/// [Liskov Substitution Principle] ("LSP"), because code that is valid for
|
||||
/// the superclass may no longer be valid for the subclass.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// from typing import ClassVar
|
||||
///
|
||||
/// class Base:
|
||||
/// instance_attr: int
|
||||
/// class_attr: ClassVar[int]
|
||||
///
|
||||
/// class Sub(Base):
|
||||
/// instance_attr: ClassVar[int] # error: [invalid-attribute-override]
|
||||
/// class_attr: int # error: [invalid-attribute-override]
|
||||
/// ```
|
||||
///
|
||||
/// [Liskov Substitution Principle]: https://en.wikipedia.org/wiki/Liskov_substitution_principle
|
||||
pub(crate) static INVALID_ATTRIBUTE_OVERRIDE = {
|
||||
summary: "detects attribute overrides that change class-variable or instance-variable behavior",
|
||||
status: LintStatus::stable("0.0.33"),
|
||||
default_level: Level::Error,
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// ## What it does
|
||||
/// Detects method overrides that violate the [Liskov Substitution Principle] ("LSP").
|
||||
|
||||
@@ -12,7 +12,7 @@ use rustc_hash::FxHashSet;
|
||||
use crate::{
|
||||
Db,
|
||||
lint::LintId,
|
||||
place::{DefinedPlace, Place},
|
||||
place::{DefinedPlace, Place, PlaceAndQualifiers, TypeOrigin},
|
||||
types::{
|
||||
CallableType, ClassBase, ClassLiteral, ClassType, KnownClass, Parameter, Parameters,
|
||||
Signature, StaticClassLiteral, Type, TypeContext, TypeQualifiers,
|
||||
@@ -21,10 +21,11 @@ use crate::{
|
||||
constraints::ConstraintSetBuilder,
|
||||
context::InferContext,
|
||||
diagnostic::{
|
||||
INVALID_ASSIGNMENT, INVALID_DATACLASS, INVALID_EXPLICIT_OVERRIDE,
|
||||
INVALID_METHOD_OVERRIDE, INVALID_NAMED_TUPLE, INVALID_NAMED_TUPLE_OVERRIDE,
|
||||
OVERRIDE_OF_FINAL_METHOD, OVERRIDE_OF_FINAL_VARIABLE, report_invalid_method_override,
|
||||
report_overridden_final_method, report_overridden_final_variable,
|
||||
INVALID_ASSIGNMENT, INVALID_ATTRIBUTE_OVERRIDE, INVALID_DATACLASS,
|
||||
INVALID_EXPLICIT_OVERRIDE, INVALID_METHOD_OVERRIDE, INVALID_NAMED_TUPLE,
|
||||
INVALID_NAMED_TUPLE_OVERRIDE, OVERRIDE_OF_FINAL_METHOD, OVERRIDE_OF_FINAL_VARIABLE,
|
||||
report_invalid_method_override, report_overridden_final_method,
|
||||
report_overridden_final_variable,
|
||||
},
|
||||
enums::{EnumMetadata, enum_metadata},
|
||||
function::{FunctionDecorators, FunctionType, KnownFunction},
|
||||
@@ -132,41 +133,6 @@ fn check_class_declaration<'db>(
|
||||
class_scope: ScopeId<'db>,
|
||||
member: &MemberWithDefinition<'db>,
|
||||
) {
|
||||
/// Salsa-tracked query to check whether any of the definitions of a symbol
|
||||
/// in a superclass scope are function definitions.
|
||||
///
|
||||
/// We need to know this for compatibility with pyright and mypy, neither of which emit an error
|
||||
/// on `C.f` here:
|
||||
///
|
||||
/// ```python
|
||||
/// from typing import final
|
||||
///
|
||||
/// class A:
|
||||
/// @final
|
||||
/// def f(self) -> None: ...
|
||||
///
|
||||
/// class B:
|
||||
/// f = A.f
|
||||
///
|
||||
/// class C(B):
|
||||
/// def f(self) -> None: ... # no error here
|
||||
/// ```
|
||||
///
|
||||
/// This is a Salsa-tracked query because it has to look at the AST node for the definition,
|
||||
/// which might be in a different Python module. If this weren't a tracked query, we could
|
||||
/// introduce cross-module dependencies and over-invalidation.
|
||||
#[salsa::tracked(heap_size=ruff_memory_usage::heap_size)]
|
||||
fn is_function_definition<'db>(
|
||||
db: &'db dyn Db,
|
||||
scope: ScopeId<'db>,
|
||||
symbol: ScopedSymbolId,
|
||||
) -> bool {
|
||||
use_def_map(db, scope)
|
||||
.end_of_scope_symbol_bindings(symbol)
|
||||
.filter_map(|binding| binding.binding.definition())
|
||||
.any(|definition| definition.kind(db).is_function_def())
|
||||
}
|
||||
|
||||
let db = context.db();
|
||||
|
||||
let MemberWithDefinition {
|
||||
@@ -176,10 +142,11 @@ fn check_class_declaration<'db>(
|
||||
|
||||
let instance_of_class = Type::instance(db, class);
|
||||
|
||||
let subclass_instance_member = instance_of_class.member(db, &member.name);
|
||||
let Place::Defined(DefinedPlace {
|
||||
ty: type_on_subclass_instance,
|
||||
..
|
||||
}) = instance_of_class.member(db, &member.name).place
|
||||
}) = subclass_instance_member.place
|
||||
else {
|
||||
return;
|
||||
};
|
||||
@@ -324,11 +291,13 @@ fn check_class_declaration<'db>(
|
||||
let mut overridden_final_method = None;
|
||||
let mut overridden_final_variable: Option<(ClassType<'db>, Option<Definition<'db>>)> = None;
|
||||
let is_private_member = is_mangled_private(member.name.as_str());
|
||||
let mut subclass_variable_kind: Option<Option<VariableKind>> = None;
|
||||
|
||||
// Track the first superclass that defines this method (the "immediate parent" for this method).
|
||||
// We need this to check if parent itself already has an LSP violation with an ancestor.
|
||||
// If so, we shouldn't report the same violation for the child class.
|
||||
let mut immediate_parent_method: Option<(ClassType<'db>, Type<'db>)> = None;
|
||||
let mut immediate_parent_variable_kind: Option<(ClassType<'db>, VariableKind)> = None;
|
||||
|
||||
if !is_private_member {
|
||||
for class_base in class.iter_mro(db).skip(1) {
|
||||
@@ -382,12 +351,12 @@ fn check_class_declaration<'db>(
|
||||
.unwrap_or_default();
|
||||
}
|
||||
|
||||
let superclass_instance_member =
|
||||
Type::instance(db, superclass).member(db, &member.name);
|
||||
let Place::Defined(DefinedPlace {
|
||||
ty: superclass_type,
|
||||
..
|
||||
}) = Type::instance(db, superclass)
|
||||
.member(db, &member.name)
|
||||
.place
|
||||
}) = superclass_instance_member.place
|
||||
else {
|
||||
// If not defined on any superclass, no point in continuing to walk up the MRO
|
||||
break;
|
||||
@@ -463,11 +432,75 @@ fn check_class_declaration<'db>(
|
||||
continue;
|
||||
}
|
||||
|
||||
if !configuration.check_liskov_violations() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if configuration.check_attribute_liskov_violations() {
|
||||
if let Some(superclass_variable_kind) =
|
||||
effective_superclass_variable_kind(db, superclass, member.name.clone())
|
||||
{
|
||||
if immediate_parent_variable_kind.is_none() {
|
||||
immediate_parent_variable_kind =
|
||||
Some((superclass, superclass_variable_kind));
|
||||
}
|
||||
|
||||
let subclass_kind = *subclass_variable_kind.get_or_insert_with(|| {
|
||||
variable_kind(
|
||||
db,
|
||||
class.own_class_member(db, None, &member.name).inner,
|
||||
subclass_instance_member,
|
||||
)
|
||||
});
|
||||
|
||||
if let Some(subclass_kind) = subclass_kind
|
||||
&& subclass_kind != superclass_variable_kind
|
||||
{
|
||||
// An unannotated class-body assignment can inherit an overridden `ClassVar`
|
||||
// declaration instead of introducing a conflicting instance variable. This
|
||||
// also applies to augmented assignments after the initial class-body
|
||||
// assignment, e.g. `epilog = "..."; epilog += "..."`.
|
||||
if subclass_kind == VariableKind::Instance
|
||||
&& superclass_variable_kind == VariableKind::Class
|
||||
&& matches!(
|
||||
first_reachable_definition.kind(db),
|
||||
DefinitionKind::Assignment(_)
|
||||
| DefinitionKind::AugmentedAssignment(_)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some((immediate_parent, immediate_parent_kind)) =
|
||||
immediate_parent_variable_kind
|
||||
&& immediate_parent != superclass
|
||||
&& immediate_parent.is_subclass_of(db, superclass)
|
||||
&& immediate_parent_kind != superclass_variable_kind
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let superclass_definition = superclass_symbol_id
|
||||
.and_then(|id| symbol_definition(db, superclass_scope, id));
|
||||
report_invalid_attribute_override(
|
||||
context,
|
||||
&member.name,
|
||||
*first_reachable_definition,
|
||||
superclass,
|
||||
superclass_definition,
|
||||
subclass_kind,
|
||||
superclass_variable_kind,
|
||||
);
|
||||
liskov_diagnostic_emitted = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !configuration.check_method_liskov_violations() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Check Liskov on non-methods too
|
||||
let Type::FunctionLiteral(subclass_function) = member.ty else {
|
||||
continue;
|
||||
};
|
||||
@@ -590,6 +623,287 @@ fn check_class_declaration<'db>(
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether an attribute declaration is a class variable or an instance variable.
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, salsa::Update, get_size2::GetSize)]
|
||||
enum VariableKind {
|
||||
/// A variable annotated with `ClassVar`.
|
||||
Class,
|
||||
/// An instance variable, including an unannotated class-body assignment.
|
||||
Instance,
|
||||
}
|
||||
|
||||
impl VariableKind {
|
||||
/// Returns the wording used for this variable kind in diagnostics.
|
||||
const fn description(self) -> &'static str {
|
||||
match self {
|
||||
VariableKind::Class => "class variable",
|
||||
VariableKind::Instance => "instance variable",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the variable kind for a superclass member.
|
||||
fn superclass_variable_kind<'db>(
|
||||
db: &'db dyn Db,
|
||||
superclass_scope: ScopeId<'db>,
|
||||
superclass_symbol_id: Option<ScopedSymbolId>,
|
||||
class_member: PlaceAndQualifiers<'db>,
|
||||
instance_member: PlaceAndQualifiers<'db>,
|
||||
) -> Option<VariableKind> {
|
||||
// Method definitions and properties are not instance-variable declarations. Check the symbol
|
||||
// definition before class/instance member lookup can erase that distinction. For example,
|
||||
// resolving an abstract `@property def f(self) -> int` through instance-member lookup would
|
||||
// make it look like an instance variable of type `int`, causing this rule to report
|
||||
// `f: ClassVar[int]` as an invalid attribute override even though the superclass member is not
|
||||
// an instance-attribute declaration.
|
||||
if superclass_symbol_id.is_some_and(|id| is_function_definition(db, superclass_scope, id)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Final attributes have their own override rule and diagnostic. Treating them as class
|
||||
// variables here would report both diagnostics for the same override.
|
||||
if class_member.qualifiers.contains(TypeQualifiers::FINAL) {
|
||||
return None;
|
||||
}
|
||||
|
||||
variable_kind(db, class_member, instance_member)
|
||||
}
|
||||
|
||||
/// Returns the variable kind for a superclass member, preserving inherited `ClassVar` declarations
|
||||
/// through unannotated class-body assignments.
|
||||
///
|
||||
/// For example, `Intermediate.x = 1` inherits the pure-class-variable declaration from `Base`, so
|
||||
/// `Sub.x: ClassVar[int]` should not be reported as overriding an instance variable:
|
||||
///
|
||||
/// ```python
|
||||
/// from typing import ClassVar
|
||||
///
|
||||
/// class Base:
|
||||
/// x: ClassVar[int]
|
||||
///
|
||||
/// class Intermediate(Base):
|
||||
/// x = 1
|
||||
///
|
||||
/// class Sub(Intermediate):
|
||||
/// x: ClassVar[int] = 2
|
||||
/// ```
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
#[salsa::tracked(heap_size=ruff_memory_usage::heap_size)]
|
||||
fn effective_superclass_variable_kind<'db>(
|
||||
db: &'db dyn Db,
|
||||
superclass: ClassType<'db>,
|
||||
name: Name,
|
||||
) -> Option<VariableKind> {
|
||||
let inherited_variable_kind = || {
|
||||
superclass
|
||||
.iter_mro(db)
|
||||
.skip(1)
|
||||
.filter_map(ClassBase::into_class)
|
||||
.find_map(|base| effective_superclass_variable_kind(db, base, name.clone()))
|
||||
};
|
||||
|
||||
let (superclass_literal, superclass_specialization) = superclass.static_class_literal(db)?;
|
||||
let superclass_scope = superclass_literal.body_scope(db);
|
||||
let superclass_symbol_table = place_table(db, superclass_scope);
|
||||
let superclass_symbol_id = superclass_symbol_table.symbol_id(&name);
|
||||
|
||||
let has_own_member = if let Some(id) = superclass_symbol_id {
|
||||
let superclass_symbol = superclass_symbol_table.symbol(id);
|
||||
superclass_symbol.is_bound() || superclass_symbol.is_declared()
|
||||
} else {
|
||||
superclass_literal
|
||||
.own_synthesized_member(db, superclass_specialization, None, &name)
|
||||
.is_some()
|
||||
};
|
||||
|
||||
if has_own_member {
|
||||
let superclass_variable_kind = superclass_variable_kind(
|
||||
db,
|
||||
superclass_scope,
|
||||
superclass_symbol_id,
|
||||
superclass.own_class_member(db, None, &name).inner,
|
||||
Type::instance(db, superclass).member(db, &name),
|
||||
);
|
||||
|
||||
if superclass_variable_kind == Some(VariableKind::Instance)
|
||||
&& superclass_symbol_id.is_some_and(|id| {
|
||||
symbol_definition(db, superclass_scope, id).is_some_and(|definition| {
|
||||
matches!(
|
||||
definition.kind(db),
|
||||
DefinitionKind::Assignment(_) | DefinitionKind::AugmentedAssignment(_)
|
||||
)
|
||||
})
|
||||
})
|
||||
&& inherited_variable_kind() == Some(VariableKind::Class)
|
||||
{
|
||||
return Some(VariableKind::Class);
|
||||
}
|
||||
|
||||
if superclass_variable_kind.is_some() {
|
||||
return superclass_variable_kind;
|
||||
}
|
||||
}
|
||||
|
||||
inherited_variable_kind()
|
||||
}
|
||||
|
||||
/// Salsa-tracked query to check whether any of the definitions of a symbol
|
||||
/// in a superclass scope are function definitions.
|
||||
///
|
||||
/// We need to know this for compatibility with pyright and mypy, neither of which emit an error
|
||||
/// on `C.f` here:
|
||||
///
|
||||
/// ```python
|
||||
/// from typing import final
|
||||
///
|
||||
/// class A:
|
||||
/// @final
|
||||
/// def f(self) -> None: ...
|
||||
///
|
||||
/// class B:
|
||||
/// f = A.f
|
||||
///
|
||||
/// class C(B):
|
||||
/// def f(self) -> None: ... # no error here
|
||||
/// ```
|
||||
///
|
||||
/// This is a Salsa-tracked query because it has to look at the AST node for the definition,
|
||||
/// which might be in a different Python module. If this weren't a tracked query, we could
|
||||
/// introduce cross-module dependencies and over-invalidation.
|
||||
#[salsa::tracked(heap_size=ruff_memory_usage::heap_size)]
|
||||
fn is_function_definition<'db>(
|
||||
db: &'db dyn Db,
|
||||
scope: ScopeId<'db>,
|
||||
symbol: ScopedSymbolId,
|
||||
) -> bool {
|
||||
use_def_map(db, scope)
|
||||
.end_of_scope_symbol_bindings(symbol)
|
||||
.filter_map(|binding| binding.binding.definition())
|
||||
.any(|definition| definition.kind(db).is_function_def())
|
||||
}
|
||||
|
||||
/// Returns the variable kind for an attribute if it should participate in `ClassVar` override checks.
|
||||
fn variable_kind<'db>(
|
||||
db: &'db dyn Db,
|
||||
class_member: PlaceAndQualifiers<'db>,
|
||||
instance_member: PlaceAndQualifiers<'db>,
|
||||
) -> Option<VariableKind> {
|
||||
if class_member.is_class_var() || instance_member.is_class_var() {
|
||||
return Some(VariableKind::Class);
|
||||
}
|
||||
|
||||
// A `Final` attribute behaves like a class variable, but final overrides are diagnosed by
|
||||
// `override-of-final-variable` instead of this rule.
|
||||
if class_member.qualifiers.contains(TypeQualifiers::FINAL) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// A method definition is a descriptor in the class body, not an instance variable declaration,
|
||||
// even though instance lookup binds it as a method. It should therefore not participate in the
|
||||
// class-variable vs. instance-variable declaration check. For example, `Sub.f` here is a
|
||||
// descriptor stored on the class, not an instance attribute:
|
||||
//
|
||||
// ```python
|
||||
// class Base:
|
||||
// f: ClassVar[int]
|
||||
//
|
||||
// class Sub(Base):
|
||||
// def f(self) -> int: ...
|
||||
// ```
|
||||
if matches!(
|
||||
class_member.place,
|
||||
Place::Defined(DefinedPlace {
|
||||
ty: Type::FunctionLiteral(_),
|
||||
..
|
||||
})
|
||||
) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Descriptor values are not normal instance variables: lookup calls `__get__`, so the value
|
||||
// exposed through an instance can differ from the value stored on the class. For example,
|
||||
// `attr = property(lambda self: 1)` installs a descriptor value, so `C().attr` exposes the
|
||||
// getter return type instead of the `property` object. By contrast, `attr: Descriptor` only
|
||||
// annotates an instance attribute; the annotated type having `__get__` does not make `C.attr`
|
||||
// a descriptor value.
|
||||
if let Place::Defined(DefinedPlace {
|
||||
ty: class_member_ty,
|
||||
origin: TypeOrigin::Inferred,
|
||||
..
|
||||
}) = class_member.place
|
||||
&& class_member_ty
|
||||
.class_member(db, "__get__".into())
|
||||
.place
|
||||
.ignore_possibly_undefined()
|
||||
.is_some()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(VariableKind::Instance)
|
||||
}
|
||||
|
||||
/// Returns the definition to use as the secondary annotation for an overridden symbol.
|
||||
fn symbol_definition<'db>(
|
||||
db: &'db dyn Db,
|
||||
scope: ScopeId<'db>,
|
||||
symbol: ScopedSymbolId,
|
||||
) -> Option<Definition<'db>> {
|
||||
use_def_map(db, scope)
|
||||
.end_of_scope_symbol_declarations(symbol)
|
||||
.find_map(|declaration| declaration.declaration.definition())
|
||||
.or_else(|| {
|
||||
use_def_map(db, scope)
|
||||
.end_of_scope_symbol_bindings(symbol)
|
||||
.find_map(|binding| binding.binding.definition())
|
||||
})
|
||||
}
|
||||
|
||||
/// Reports an invalid override between a class variable and an instance variable.
|
||||
fn report_invalid_attribute_override<'db>(
|
||||
context: &InferContext<'db, '_>,
|
||||
member: &Name,
|
||||
subclass_definition: Definition<'db>,
|
||||
superclass: ClassType<'db>,
|
||||
superclass_definition: Option<Definition<'db>>,
|
||||
subclass_kind: VariableKind,
|
||||
superclass_kind: VariableKind,
|
||||
) {
|
||||
let db = context.db();
|
||||
|
||||
let Some(builder) = context.report_lint(
|
||||
&INVALID_ATTRIBUTE_OVERRIDE,
|
||||
subclass_definition.focus_range(db, context.module()),
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let superclass_name = superclass.name(db);
|
||||
let superclass_member = format!("{superclass_name}.{member}");
|
||||
let subclass_kind = subclass_kind.description();
|
||||
let superclass_kind = superclass_kind.description();
|
||||
|
||||
let mut diagnostic =
|
||||
builder.into_diagnostic(format_args!("Invalid override of attribute `{member}`"));
|
||||
diagnostic.set_primary_message(format_args!(
|
||||
"{subclass_kind} cannot override {superclass_kind} `{superclass_member}`"
|
||||
));
|
||||
diagnostic.info("This violates the Liskov Substitution Principle");
|
||||
|
||||
if let Some(superclass_definition) = superclass_definition
|
||||
&& superclass_definition.file(db) == context.file()
|
||||
{
|
||||
diagnostic.annotate(
|
||||
Annotation::secondary(
|
||||
context.span(superclass_definition.focus_range(db, context.module())),
|
||||
)
|
||||
.message(format_args!(
|
||||
"{superclass_kind} `{superclass_member}` declared here"
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub(super) enum MethodKind<'db> {
|
||||
Synthesized(CodeGeneratorKind<'db>),
|
||||
@@ -600,15 +914,16 @@ pub(super) enum MethodKind<'db> {
|
||||
bitflags! {
|
||||
/// Bitflags representing which override-related rules have been enabled.
|
||||
#[derive(Default, Debug, Copy, Clone)]
|
||||
struct OverrideRulesConfig: u8 {
|
||||
struct OverrideRulesConfig: u16 {
|
||||
const LISKOV_METHODS = 1 << 0;
|
||||
const EXPLICIT_OVERRIDE = 1 << 1;
|
||||
const FINAL_METHOD_OVERRIDDEN = 1 << 2;
|
||||
const INVALID_NAMED_TUPLE = 1 << 3;
|
||||
const NAMED_TUPLE_FIELD_OVERRIDE = 1 << 4;
|
||||
const INVALID_DATACLASS = 1 << 5;
|
||||
const FINAL_VARIABLE_OVERRIDDEN = 1 << 6;
|
||||
const INVALID_ENUM_VALUE = 1 << 7;
|
||||
const LISKOV_ATTRIBUTES = 1 << 1;
|
||||
const EXPLICIT_OVERRIDE = 1 << 2;
|
||||
const FINAL_METHOD_OVERRIDDEN = 1 << 3;
|
||||
const INVALID_NAMED_TUPLE = 1 << 4;
|
||||
const NAMED_TUPLE_FIELD_OVERRIDE = 1 << 5;
|
||||
const INVALID_DATACLASS = 1 << 6;
|
||||
const FINAL_VARIABLE_OVERRIDDEN = 1 << 7;
|
||||
const INVALID_ENUM_VALUE = 1 << 8;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,6 +937,9 @@ impl From<&InferContext<'_, '_>> for OverrideRulesConfig {
|
||||
if rule_selection.is_enabled(LintId::of(&INVALID_METHOD_OVERRIDE)) {
|
||||
config |= OverrideRulesConfig::LISKOV_METHODS;
|
||||
}
|
||||
if rule_selection.is_enabled(LintId::of(&INVALID_ATTRIBUTE_OVERRIDE)) {
|
||||
config |= OverrideRulesConfig::LISKOV_ATTRIBUTES;
|
||||
}
|
||||
if rule_selection.is_enabled(LintId::of(&INVALID_EXPLICIT_OVERRIDE)) {
|
||||
config |= OverrideRulesConfig::EXPLICIT_OVERRIDE;
|
||||
}
|
||||
@@ -657,6 +975,15 @@ impl OverrideRulesConfig {
|
||||
self.contains(OverrideRulesConfig::LISKOV_METHODS)
|
||||
}
|
||||
|
||||
const fn check_attribute_liskov_violations(self) -> bool {
|
||||
self.contains(OverrideRulesConfig::LISKOV_ATTRIBUTES)
|
||||
}
|
||||
|
||||
const fn check_liskov_violations(self) -> bool {
|
||||
self.contains(OverrideRulesConfig::LISKOV_METHODS)
|
||||
|| self.contains(OverrideRulesConfig::LISKOV_ATTRIBUTES)
|
||||
}
|
||||
|
||||
const fn check_final_method_overridden(self) -> bool {
|
||||
self.contains(OverrideRulesConfig::FINAL_METHOD_OVERRIDDEN)
|
||||
}
|
||||
|
||||
Generated
+10
@@ -620,6 +620,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"invalid-attribute-override": {
|
||||
"title": "detects attribute overrides that change class-variable or instance-variable behavior",
|
||||
"description": "## What it does\nDetects attribute overrides that change whether an inherited attribute\nis a class variable or an instance variable.\n\nThis rule currently only covers class-variable and instance-variable\ncategory changes.\n\n## Why is this bad?\nPure class variables and instance variables have different access and\nassignment behavior. Overriding one with the other violates the\n[Liskov Substitution Principle] (\"LSP\"), because code that is valid for\nthe superclass may no longer be valid for the subclass.\n\n## Example\n```python\nfrom typing import ClassVar\n\nclass Base:\n instance_attr: int\n class_attr: ClassVar[int]\n\nclass Sub(Base):\n instance_attr: ClassVar[int] # error: [invalid-attribute-override]\n class_attr: int # error: [invalid-attribute-override]\n```\n\n[Liskov Substitution Principle]: https://en.wikipedia.org/wiki/Liskov_substitution_principle",
|
||||
"default": "error",
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Level"
|
||||
}
|
||||
]
|
||||
},
|
||||
"invalid-await": {
|
||||
"title": "detects awaiting on types that don't support it",
|
||||
"description": "## What it does\nChecks for `await` being used with types that are not [Awaitable].\n\n## Why is this bad?\nSuch expressions will lead to `TypeError` being raised at runtime.\n\n## Examples\n```python\nimport asyncio\n\nclass InvalidAwait:\n def __await__(self) -> int:\n return 5\n\nasync def main() -> None:\n await InvalidAwait() # error: [invalid-await]\n await 42 # error: [invalid-await]\n\nasyncio.run(main())\n```\n\n[Awaitable]: https://docs.python.org/3/library/collections.abc.html#collections.abc.Awaitable",
|
||||
|
||||
Reference in New Issue
Block a user