mirror of https://github.com/astral-sh/ruff
Merge remote-tracking branch 'origin/main' into dcreager/breakest-the-cycle
* origin/main: [ty] Support implicit type of `cls` in signatures (#21771) [ty] add `SyntheticTypedDictType` and implement `normalized` and `is_equivalent_to` (#21784) [ty] Fix disjointness checks with type-of `@final` classes (#21770) [ty] Fix negation upper bounds in constraint sets (#21897)
This commit is contained in:
commit
826e2f331b
|
|
@ -39,7 +39,7 @@ def test(): -> "int":
|
|||
Default level: <a href="../rules.md#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%20call-non-callable" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L135" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L134" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ Calling a non-callable object will raise a `TypeError` at runtime.
|
|||
Default level: <a href="../rules.md#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%20conflicting-argument-forms" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L179" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L178" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ f(int) # error
|
|||
Default level: <a href="../rules.md#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%20conflicting-declarations" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L205" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L204" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ a = 1
|
|||
Default level: <a href="../rules.md#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%20conflicting-metaclass" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L230" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L229" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ class C(A, B): ...
|
|||
Default level: <a href="../rules.md#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%20cyclic-class-definition" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L256" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L255" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -190,7 +190,7 @@ class B(A): ...
|
|||
Default level: <a href="../rules.md#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/1.0.0">1.0.0</a>) ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20cyclic-type-alias-definition" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L282" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L281" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ type B = A
|
|||
Default level: <a href="../rules.md#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%20duplicate-base" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L343" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L342" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ class B(A, A): ...
|
|||
Default level: <a href="../rules.md#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%20duplicate-kw-only" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L364" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L363" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -357,7 +357,7 @@ def test(): -> "Literal[5]":
|
|||
Default level: <a href="../rules.md#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%20inconsistent-mro" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L590" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L589" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -387,7 +387,7 @@ class C(A, B): ...
|
|||
Default level: <a href="../rules.md#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%20index-out-of-bounds" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L614" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L613" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -413,7 +413,7 @@ t[3] # IndexError: tuple index out of range
|
|||
Default level: <a href="../rules.md#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%20instance-layout-conflict" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L396" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L395" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -502,7 +502,7 @@ an atypical memory layout.
|
|||
Default level: <a href="../rules.md#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%20invalid-argument-type" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L668" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L667" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -529,7 +529,7 @@ func("foo") # error: [invalid-argument-type]
|
|||
Default level: <a href="../rules.md#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%20invalid-assignment" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L708" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L707" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -557,7 +557,7 @@ a: int = ''
|
|||
Default level: <a href="../rules.md#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%20invalid-attribute-access" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1998" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1997" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -591,7 +591,7 @@ C.instance_var = 3 # error: Cannot assign to instance variable
|
|||
Default level: <a href="../rules.md#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%20invalid-await" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L730" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L729" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -627,7 +627,7 @@ asyncio.run(main())
|
|||
Default level: <a href="../rules.md#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%20invalid-base" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L760" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L759" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -651,7 +651,7 @@ class A(42): ... # error: [invalid-base]
|
|||
Default level: <a href="../rules.md#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%20invalid-context-manager" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L811" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L810" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -678,7 +678,7 @@ with 1:
|
|||
Default level: <a href="../rules.md#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%20invalid-declaration" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L832" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L831" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -707,7 +707,7 @@ a: str
|
|||
Default level: <a href="../rules.md#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%20invalid-exception-caught" 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#L854" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -751,7 +751,7 @@ except ZeroDivisionError:
|
|||
Default level: <a href="../rules.md#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%20invalid-explicit-override" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1668" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1667" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -793,7 +793,7 @@ class D(A):
|
|||
Default level: <a href="../rules.md#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%20invalid-generic-class" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L891" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L890" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -826,7 +826,7 @@ class C[U](Generic[T]): ...
|
|||
Default level: <a href="../rules.md#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%20invalid-key" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L635" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L634" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -865,7 +865,7 @@ carol = Person(name="Carol", age=25) # typo!
|
|||
Default level: <a href="../rules.md#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%20invalid-legacy-type-variable" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L917" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L916" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -900,7 +900,7 @@ def f(t: TypeVar("U")): ...
|
|||
Default level: <a href="../rules.md#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%20invalid-metaclass" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1014" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1013" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -934,7 +934,7 @@ class B(metaclass=f): ...
|
|||
Default level: <a href="../rules.md#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%20invalid-method-override" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2126" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2125" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1041,7 +1041,7 @@ Correct use of `@override` is enforced by ty's `invalid-explicit-override` rule.
|
|||
Default level: <a href="../rules.md#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%20invalid-named-tuple" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L542" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L541" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1095,7 +1095,7 @@ AttributeError: Cannot overwrite NamedTuple attribute _asdict
|
|||
Default level: <a href="../rules.md#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/1.0.0">1.0.0</a>) ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-newtype" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L990" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L989" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1125,7 +1125,7 @@ Baz = NewType("Baz", int | str) # error: invalid base for `typing.NewType`
|
|||
Default level: <a href="../rules.md#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%20invalid-overload" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1041" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1040" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1175,7 +1175,7 @@ def foo(x: int) -> int: ...
|
|||
Default level: <a href="../rules.md#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%20invalid-parameter-default" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1140" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1139" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1201,7 +1201,7 @@ def f(a: int = ''): ...
|
|||
Default level: <a href="../rules.md#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%20invalid-paramspec" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L945" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L944" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1232,7 +1232,7 @@ P2 = ParamSpec("S2") # error: ParamSpec name must match the variable it's assig
|
|||
Default level: <a href="../rules.md#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%20invalid-protocol" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L478" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L477" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1266,7 +1266,7 @@ TypeError: Protocols can only inherit from other protocols, got <class 'int'>
|
|||
Default level: <a href="../rules.md#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%20invalid-raise" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1160" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1159" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1315,7 +1315,7 @@ def g():
|
|||
Default level: <a href="../rules.md#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%20invalid-return-type" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L689" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L688" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1340,7 +1340,7 @@ def func() -> int:
|
|||
Default level: <a href="../rules.md#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%20invalid-super-argument" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1203" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1202" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1398,7 +1398,7 @@ TODO #14889
|
|||
Default level: <a href="../rules.md#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%20invalid-type-alias-type" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L969" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L968" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1425,7 +1425,7 @@ NewAlias = TypeAliasType(get_name(), int) # error: TypeAliasType name mus
|
|||
Default level: <a href="../rules.md#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%20invalid-type-arguments" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1435" 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>
|
||||
|
||||
|
||||
|
|
@ -1472,7 +1472,7 @@ Bar[int] # error: too few arguments
|
|||
Default level: <a href="../rules.md#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%20invalid-type-checking-constant" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1242" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1241" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1502,7 +1502,7 @@ TYPE_CHECKING = ''
|
|||
Default level: <a href="../rules.md#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%20invalid-type-form" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1266" 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>
|
||||
|
||||
|
||||
|
|
@ -1532,7 +1532,7 @@ b: Annotated[int] # `Annotated` expects at least two arguments
|
|||
Default level: <a href="../rules.md#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%20invalid-type-guard-call" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1318" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1317" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1566,7 +1566,7 @@ f(10) # Error
|
|||
Default level: <a href="../rules.md#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%20invalid-type-guard-definition" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1290" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1289" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1600,7 +1600,7 @@ class C:
|
|||
Default level: <a href="../rules.md#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%20invalid-type-variable-constraints" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1346" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1345" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1635,7 +1635,7 @@ T = TypeVar('T', bound=str) # valid bound TypeVar
|
|||
Default level: <a href="../rules.md#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%20missing-argument" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1375" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1374" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1660,7 +1660,7 @@ func() # TypeError: func() missing 1 required positional argument: 'x'
|
|||
Default level: <a href="../rules.md#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%20missing-typed-dict-key" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2099" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2098" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1693,7 +1693,7 @@ alice["age"] # KeyError
|
|||
Default level: <a href="../rules.md#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%20no-matching-overload" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1394" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1393" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1722,7 +1722,7 @@ func("string") # error: [no-matching-overload]
|
|||
Default level: <a href="../rules.md#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%20non-subscriptable" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1417" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1416" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1746,7 +1746,7 @@ Subscripting an object that does not support it will raise a `TypeError` at runt
|
|||
Default level: <a href="../rules.md#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%20not-iterable" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1476" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1475" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1772,7 +1772,7 @@ for i in 34: # TypeError: 'int' object is not iterable
|
|||
Default level: <a href="../rules.md#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%20override-of-final-method" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1641" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1640" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1805,7 +1805,7 @@ class B(A):
|
|||
Default level: <a href="../rules.md#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%20parameter-already-assigned" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1527" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1526" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1832,7 +1832,7 @@ f(1, x=2) # Error raised here
|
|||
Default level: <a href="../rules.md#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%20positional-only-parameter-as-kwarg" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1852" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1851" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1890,7 +1890,7 @@ def test(): -> "int":
|
|||
Default level: <a href="../rules.md#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%20static-assert-error" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1974" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1973" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1920,7 +1920,7 @@ static_assert(int(2.0 * 3.0) == 6) # error: does not have a statically known tr
|
|||
Default level: <a href="../rules.md#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%20subclass-of-final-class" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1618" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1617" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1949,7 +1949,7 @@ class B(A): ... # Error raised here
|
|||
Default level: <a href="../rules.md#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.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%20super-call-in-named-tuple-method" target="_blank">Related issues</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>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1785" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1983,7 +1983,7 @@ class F(NamedTuple):
|
|||
Default level: <a href="../rules.md#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%20too-many-positional-arguments" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1726" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1725" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2010,7 +2010,7 @@ f("foo") # Error raised here
|
|||
Default level: <a href="../rules.md#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%20type-assertion-failure" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1704" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1703" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2038,7 +2038,7 @@ def _(x: int):
|
|||
Default level: <a href="../rules.md#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%20unavailable-implicit-super-arguments" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1747" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1746" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2084,7 +2084,7 @@ class A:
|
|||
Default level: <a href="../rules.md#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%20unknown-argument" 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#L1830" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2111,7 +2111,7 @@ f(x=1, y=2) # Error raised here
|
|||
Default level: <a href="../rules.md#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%20unresolved-attribute" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1873" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1872" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2139,7 +2139,7 @@ A().foo # AttributeError: 'A' object has no attribute 'foo'
|
|||
Default level: <a href="../rules.md#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%20unresolved-import" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1895" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1894" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2164,7 +2164,7 @@ import foo # ModuleNotFoundError: No module named 'foo'
|
|||
Default level: <a href="../rules.md#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%20unresolved-reference" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1914" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1913" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2189,7 +2189,7 @@ print(x) # NameError: name 'x' is not defined
|
|||
Default level: <a href="../rules.md#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%20unsupported-bool-conversion" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1496" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1495" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2226,7 +2226,7 @@ b1 < b2 < b1 # exception raised here
|
|||
Default level: <a href="../rules.md#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%20unsupported-operator" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1933" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1932" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2254,7 +2254,7 @@ A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'
|
|||
Default level: <a href="../rules.md#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%20zero-stepsize-in-slice" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1955" 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>
|
||||
|
||||
|
||||
|
|
@ -2279,7 +2279,7 @@ l[1:10:0] # ValueError: slice step cannot be zero
|
|||
Default level: <a href="../rules.md#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%20ambiguous-protocol-member" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L507" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L506" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2320,7 +2320,7 @@ class SubProto(BaseProto, Protocol):
|
|||
Default level: <a href="../rules.md#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%20deprecated" 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#L321" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2408,7 +2408,7 @@ a = 20 / 0 # type: ignore
|
|||
Default level: <a href="../rules.md#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%20possibly-missing-attribute" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1548" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1547" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2436,7 +2436,7 @@ A.c # AttributeError: type object 'A' has no attribute 'c'
|
|||
Default level: <a href="../rules.md#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%20possibly-missing-implicit-call" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L153" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L152" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2468,7 +2468,7 @@ A()[0] # TypeError: 'A' object is not subscriptable
|
|||
Default level: <a href="../rules.md#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%20possibly-missing-import" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1570" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1569" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2500,7 +2500,7 @@ from module import a # ImportError: cannot import name 'a' from 'module'
|
|||
Default level: <a href="../rules.md#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%20redundant-cast" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2026" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2025" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2527,7 +2527,7 @@ cast(int, f()) # Redundant
|
|||
Default level: <a href="../rules.md#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%20undefined-reveal" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1813" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1812" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2551,7 +2551,7 @@ reveal_type(1) # NameError: name 'reveal_type' is not defined
|
|||
Default level: <a href="../rules.md#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%20unresolved-global" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2047" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2046" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2609,7 +2609,7 @@ def g():
|
|||
Default level: <a href="../rules.md#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%20unsupported-base" target="_blank">Related issues</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>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L777" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2648,7 +2648,7 @@ class D(C): ... # error: [unsupported-base]
|
|||
Default level: <a href="../rules.md#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%20useless-overload-body" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1084" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1083" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2711,7 +2711,7 @@ def foo(x: int | str) -> int | str:
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'ignore'."><code>ignore</code></a> ·
|
||||
Preview (since <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%20division-by-zero" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L304" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L303" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2735,7 +2735,7 @@ Dividing by zero raises a `ZeroDivisionError` at runtime.
|
|||
Default level: <a href="../rules.md#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%20possibly-unresolved-reference" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1596" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1595" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -607,7 +607,7 @@ class X:
|
|||
def __init__(self, val: int): ...
|
||||
def make_another(self) -> Self:
|
||||
reveal_type(self.__new__) # revealed: def __new__(cls) -> Self@__new__
|
||||
return self.__new__(X)
|
||||
return self.__new__(type(self))
|
||||
```
|
||||
|
||||
## Builtin functions and methods
|
||||
|
|
|
|||
|
|
@ -271,8 +271,7 @@ reveal_type(Person._make) # revealed: bound method <class 'Person'>._make(itera
|
|||
reveal_type(Person._asdict) # revealed: def _asdict(self) -> dict[str, Any]
|
||||
reveal_type(Person._replace) # revealed: def _replace(self, **kwargs: Any) -> Self@_replace
|
||||
|
||||
# TODO: should be `Person` once we support implicit type of `self`
|
||||
reveal_type(Person._make(("Alice", 42))) # revealed: Unknown
|
||||
reveal_type(Person._make(("Alice", 42))) # revealed: Person
|
||||
|
||||
person = Person("Alice", 42)
|
||||
|
||||
|
|
|
|||
|
|
@ -92,8 +92,7 @@ def f(x: A[int] | B):
|
|||
reveal_type(x) # revealed: A[int] | B
|
||||
|
||||
if type(x) is A:
|
||||
# TODO: this should be `A[int]`, but `A[int] | B` would be better than `Never`
|
||||
reveal_type(x) # revealed: Never
|
||||
reveal_type(x) # revealed: A[int]
|
||||
else:
|
||||
reveal_type(x) # revealed: A[int] | B
|
||||
|
||||
|
|
@ -111,8 +110,7 @@ def f(x: A[int] | B):
|
|||
if type(x) is not A:
|
||||
reveal_type(x) # revealed: A[int] | B
|
||||
else:
|
||||
# TODO: this should be `A[int]`, but `A[int] | B` would be better than `Never`
|
||||
reveal_type(x) # revealed: Never
|
||||
reveal_type(x) # revealed: A[int]
|
||||
|
||||
if type(x) is not B:
|
||||
reveal_type(x) # revealed: A[int] | B
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
source: crates/ty_test/src/lib.rs
|
||||
expression: snapshot
|
||||
---
|
||||
---
|
||||
mdtest name: typed_dict.md - `TypedDict` - Redundant cast warnings
|
||||
mdtest path: crates/ty_python_semantic/resources/mdtest/typed_dict.md
|
||||
---
|
||||
|
||||
# Python source files
|
||||
|
||||
## mdtest_snippet.py
|
||||
|
||||
```
|
||||
1 | from typing import TypedDict, cast
|
||||
2 |
|
||||
3 | class Foo2(TypedDict):
|
||||
4 | x: int
|
||||
5 |
|
||||
6 | class Bar2(TypedDict):
|
||||
7 | x: int
|
||||
8 |
|
||||
9 | foo: Foo2 = {"x": 1}
|
||||
10 | _ = cast(Foo2, foo) # error: [redundant-cast]
|
||||
11 | _ = cast(Bar2, foo) # error: [redundant-cast]
|
||||
```
|
||||
|
||||
# Diagnostics
|
||||
|
||||
```
|
||||
warning[redundant-cast]: Value is already of type `Foo2`
|
||||
--> src/mdtest_snippet.py:10:5
|
||||
|
|
||||
9 | foo: Foo2 = {"x": 1}
|
||||
10 | _ = cast(Foo2, foo) # error: [redundant-cast]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
11 | _ = cast(Bar2, foo) # error: [redundant-cast]
|
||||
|
|
||||
info: rule `redundant-cast` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
warning[redundant-cast]: Value is already of type `Bar2`
|
||||
--> src/mdtest_snippet.py:11:5
|
||||
|
|
||||
9 | foo: Foo2 = {"x": 1}
|
||||
10 | _ = cast(Foo2, foo) # error: [redundant-cast]
|
||||
11 | _ = cast(Bar2, foo) # error: [redundant-cast]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
info: `Bar2` is equivalent to `Foo2`
|
||||
info: rule `redundant-cast` is enabled by default
|
||||
|
||||
```
|
||||
|
|
@ -160,7 +160,7 @@ same also applies to enum classes with members, which are implicitly final:
|
|||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.10"
|
||||
python-version = "3.12"
|
||||
```
|
||||
|
||||
```py
|
||||
|
|
@ -180,3 +180,177 @@ def _(x: type[Foo], y: type[EllipsisType], z: type[Answer]):
|
|||
reveal_type(y) # revealed: <class 'EllipsisType'>
|
||||
reveal_type(z) # revealed: <class 'Answer'>
|
||||
```
|
||||
|
||||
## Subtyping `@final` classes
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.12"
|
||||
```
|
||||
|
||||
```py
|
||||
from typing import final, Any
|
||||
from ty_extensions import is_assignable_to, is_subtype_of, is_disjoint_from, static_assert
|
||||
|
||||
class Biv[T]: ...
|
||||
|
||||
class Cov[T]:
|
||||
def pop(self) -> T:
|
||||
raise NotImplementedError
|
||||
|
||||
class Contra[T]:
|
||||
def push(self, value: T) -> None:
|
||||
pass
|
||||
|
||||
class Inv[T]:
|
||||
x: T
|
||||
|
||||
@final
|
||||
class BivSub[T](Biv[T]): ...
|
||||
|
||||
@final
|
||||
class CovSub[T](Cov[T]): ...
|
||||
|
||||
@final
|
||||
class ContraSub[T](Contra[T]): ...
|
||||
|
||||
@final
|
||||
class InvSub[T](Inv[T]): ...
|
||||
|
||||
def _[T, U]():
|
||||
static_assert(is_subtype_of(type[BivSub[T]], type[BivSub[U]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[U]], type[BivSub[T]]))
|
||||
|
||||
# `T` and `U` could specialize to the same type.
|
||||
static_assert(not is_subtype_of(type[CovSub[T]], type[CovSub[U]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[U]], type[CovSub[T]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[ContraSub[T]], type[ContraSub[U]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[U]], type[ContraSub[T]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[InvSub[T]], type[InvSub[U]]))
|
||||
static_assert(not is_disjoint_from(type[InvSub[U]], type[InvSub[T]]))
|
||||
|
||||
def _():
|
||||
static_assert(is_subtype_of(type[BivSub[bool]], type[BivSub[int]]))
|
||||
static_assert(is_subtype_of(type[BivSub[int]], type[BivSub[bool]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[bool]], type[BivSub[int]]))
|
||||
# `BivSub[int]` and `BivSub[str]` are mutual subtypes.
|
||||
static_assert(not is_disjoint_from(type[BivSub[int]], type[BivSub[str]]))
|
||||
|
||||
static_assert(is_subtype_of(type[CovSub[bool]], type[CovSub[int]]))
|
||||
static_assert(not is_subtype_of(type[CovSub[int]], type[CovSub[bool]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[bool]], type[CovSub[int]]))
|
||||
# `CovSub[Never]` is a subtype of both `CovSub[int]` and `CovSub[str]`.
|
||||
static_assert(not is_disjoint_from(type[CovSub[int]], type[CovSub[str]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[ContraSub[bool]], type[ContraSub[int]]))
|
||||
static_assert(is_subtype_of(type[ContraSub[int]], type[ContraSub[bool]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[bool]], type[ContraSub[int]]))
|
||||
# `ContraSub[int | str]` is a subtype of both `ContraSub[int]` and `ContraSub[str]`.
|
||||
static_assert(not is_disjoint_from(type[ContraSub[int]], type[ContraSub[str]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[InvSub[bool]], type[InvSub[int]]))
|
||||
static_assert(not is_subtype_of(type[InvSub[int]], type[InvSub[bool]]))
|
||||
static_assert(is_disjoint_from(type[InvSub[int]], type[InvSub[str]]))
|
||||
# TODO: These are disjoint.
|
||||
static_assert(not is_disjoint_from(type[InvSub[bool]], type[InvSub[int]]))
|
||||
|
||||
def _[T]():
|
||||
static_assert(is_subtype_of(type[BivSub[T]], type[BivSub[Any]]))
|
||||
static_assert(is_subtype_of(type[BivSub[Any]], type[BivSub[T]]))
|
||||
static_assert(is_assignable_to(type[BivSub[T]], type[BivSub[Any]]))
|
||||
static_assert(is_assignable_to(type[BivSub[Any]], type[BivSub[T]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[T]], type[BivSub[Any]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[CovSub[T]], type[CovSub[Any]]))
|
||||
static_assert(not is_subtype_of(type[CovSub[Any]], type[CovSub[T]]))
|
||||
static_assert(is_assignable_to(type[CovSub[T]], type[CovSub[Any]]))
|
||||
static_assert(is_assignable_to(type[CovSub[Any]], type[CovSub[T]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[T]], type[CovSub[Any]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[ContraSub[T]], type[ContraSub[Any]]))
|
||||
static_assert(not is_subtype_of(type[ContraSub[Any]], type[ContraSub[T]]))
|
||||
static_assert(is_assignable_to(type[ContraSub[T]], type[ContraSub[Any]]))
|
||||
static_assert(is_assignable_to(type[ContraSub[Any]], type[ContraSub[T]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[T]], type[ContraSub[Any]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[InvSub[T]], type[InvSub[Any]]))
|
||||
static_assert(not is_subtype_of(type[InvSub[Any]], type[InvSub[T]]))
|
||||
static_assert(is_assignable_to(type[InvSub[T]], type[InvSub[Any]]))
|
||||
static_assert(is_assignable_to(type[InvSub[Any]], type[InvSub[T]]))
|
||||
static_assert(not is_disjoint_from(type[InvSub[T]], type[InvSub[Any]]))
|
||||
|
||||
def _[T, U]():
|
||||
static_assert(is_subtype_of(type[BivSub[T]], type[Biv[T]]))
|
||||
static_assert(not is_subtype_of(type[Biv[T]], type[BivSub[T]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[T]], type[Biv[T]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[U]], type[Biv[T]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[U]], type[Biv[U]]))
|
||||
|
||||
static_assert(is_subtype_of(type[CovSub[T]], type[Cov[T]]))
|
||||
static_assert(not is_subtype_of(type[Cov[T]], type[CovSub[T]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[T]], type[Cov[T]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[U]], type[Cov[T]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[U]], type[Cov[U]]))
|
||||
|
||||
static_assert(is_subtype_of(type[ContraSub[T]], type[Contra[T]]))
|
||||
static_assert(not is_subtype_of(type[Contra[T]], type[ContraSub[T]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[T]], type[Contra[T]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[U]], type[Contra[T]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[U]], type[Contra[U]]))
|
||||
|
||||
static_assert(is_subtype_of(type[InvSub[T]], type[Inv[T]]))
|
||||
static_assert(not is_subtype_of(type[Inv[T]], type[InvSub[T]]))
|
||||
static_assert(not is_disjoint_from(type[InvSub[T]], type[Inv[T]]))
|
||||
static_assert(not is_disjoint_from(type[InvSub[U]], type[Inv[T]]))
|
||||
static_assert(not is_disjoint_from(type[InvSub[U]], type[Inv[U]]))
|
||||
|
||||
def _():
|
||||
static_assert(is_subtype_of(type[BivSub[bool]], type[Biv[int]]))
|
||||
static_assert(is_subtype_of(type[BivSub[int]], type[Biv[bool]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[bool]], type[Biv[int]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[int]], type[Biv[bool]]))
|
||||
|
||||
static_assert(is_subtype_of(type[CovSub[bool]], type[Cov[int]]))
|
||||
static_assert(not is_subtype_of(type[CovSub[int]], type[Cov[bool]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[bool]], type[Cov[int]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[int]], type[Cov[bool]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[ContraSub[bool]], type[Contra[int]]))
|
||||
static_assert(is_subtype_of(type[ContraSub[int]], type[Contra[bool]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[int]], type[Contra[bool]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[bool]], type[Contra[int]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[InvSub[bool]], type[Inv[int]]))
|
||||
static_assert(not is_subtype_of(type[InvSub[int]], type[Inv[bool]]))
|
||||
# TODO: These are disjoint.
|
||||
static_assert(not is_disjoint_from(type[InvSub[bool]], type[Inv[int]]))
|
||||
# TODO: These are disjoint.
|
||||
static_assert(not is_disjoint_from(type[InvSub[int]], type[Inv[bool]]))
|
||||
|
||||
def _[T]():
|
||||
static_assert(is_subtype_of(type[BivSub[T]], type[Biv[Any]]))
|
||||
static_assert(is_subtype_of(type[BivSub[Any]], type[Biv[T]]))
|
||||
static_assert(is_assignable_to(type[BivSub[T]], type[Biv[Any]]))
|
||||
static_assert(is_assignable_to(type[BivSub[Any]], type[Biv[T]]))
|
||||
static_assert(not is_disjoint_from(type[BivSub[T]], type[Biv[Any]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[CovSub[T]], type[Cov[Any]]))
|
||||
static_assert(not is_subtype_of(type[CovSub[Any]], type[Cov[T]]))
|
||||
static_assert(is_assignable_to(type[CovSub[T]], type[Cov[Any]]))
|
||||
static_assert(is_assignable_to(type[CovSub[Any]], type[Cov[T]]))
|
||||
static_assert(not is_disjoint_from(type[CovSub[T]], type[Cov[Any]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[ContraSub[T]], type[Contra[Any]]))
|
||||
static_assert(not is_subtype_of(type[ContraSub[Any]], type[Contra[T]]))
|
||||
static_assert(is_assignable_to(type[ContraSub[T]], type[Contra[Any]]))
|
||||
static_assert(is_assignable_to(type[ContraSub[Any]], type[Contra[T]]))
|
||||
static_assert(not is_disjoint_from(type[ContraSub[T]], type[Contra[Any]]))
|
||||
|
||||
static_assert(not is_subtype_of(type[InvSub[T]], type[Inv[Any]]))
|
||||
static_assert(not is_subtype_of(type[InvSub[Any]], type[Inv[T]]))
|
||||
static_assert(is_assignable_to(type[InvSub[T]], type[Inv[Any]]))
|
||||
static_assert(is_assignable_to(type[InvSub[Any]], type[Inv[T]]))
|
||||
static_assert(not is_disjoint_from(type[InvSub[T]], type[Inv[Any]]))
|
||||
```
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ strict subtype of the lower bound, a strict supertype of the upper bound, or inc
|
|||
|
||||
```py
|
||||
from typing import Any, final, Never, Sequence
|
||||
from ty_extensions import ConstraintSet, static_assert
|
||||
from ty_extensions import ConstraintSet, Not, static_assert
|
||||
|
||||
class Super: ...
|
||||
class Base(Super): ...
|
||||
|
|
@ -207,6 +207,15 @@ def _[T]() -> None:
|
|||
static_assert(constraints == expected)
|
||||
```
|
||||
|
||||
A negated _type_ is not the same thing as a negated _range_.
|
||||
|
||||
```py
|
||||
def _[T]() -> None:
|
||||
negated_type = ConstraintSet.range(Never, T, Not[int])
|
||||
negated_constraint = ~ConstraintSet.range(Never, T, int)
|
||||
static_assert(negated_type != negated_constraint)
|
||||
```
|
||||
|
||||
## Intersection
|
||||
|
||||
The intersection of two constraint sets requires that the constraints in both sets hold. In many
|
||||
|
|
|
|||
|
|
@ -684,9 +684,8 @@ class GenericClass[T]:
|
|||
x: T # invariant
|
||||
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClass], type[GenericClass]))
|
||||
# TODO: these should not error
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClass[int]], type[GenericClass])) # error: [static-assert-error]
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClass], type[GenericClass[int]])) # error: [static-assert-error]
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClass[int]], type[GenericClass]))
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClass], type[GenericClass[int]]))
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClass[int]], type[GenericClass[int]]))
|
||||
static_assert(is_disjoint_from(TypeOf[GenericClass[str]], type[GenericClass[int]]))
|
||||
|
||||
|
|
@ -694,19 +693,17 @@ class GenericClassIntBound[T: int]:
|
|||
x: T # invariant
|
||||
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClassIntBound], type[GenericClassIntBound]))
|
||||
# TODO: these should not error
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClassIntBound[int]], type[GenericClassIntBound])) # error: [static-assert-error]
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClassIntBound], type[GenericClassIntBound[int]])) # error: [static-assert-error]
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClassIntBound[int]], type[GenericClassIntBound]))
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClassIntBound], type[GenericClassIntBound[int]]))
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericClassIntBound[int]], type[GenericClassIntBound[int]]))
|
||||
|
||||
@final
|
||||
class GenericFinalClass[T]:
|
||||
x: T # invariant
|
||||
|
||||
# TODO: these should not error
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericFinalClass], type[GenericFinalClass])) # error: [static-assert-error]
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericFinalClass[int]], type[GenericFinalClass])) # error: [static-assert-error]
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericFinalClass], type[GenericFinalClass[int]])) # error: [static-assert-error]
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericFinalClass], type[GenericFinalClass]))
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericFinalClass[int]], type[GenericFinalClass]))
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericFinalClass], type[GenericFinalClass[int]]))
|
||||
static_assert(not is_disjoint_from(TypeOf[GenericFinalClass[int]], type[GenericFinalClass[int]]))
|
||||
static_assert(is_disjoint_from(TypeOf[GenericFinalClass[str]], type[GenericFinalClass[int]]))
|
||||
```
|
||||
|
|
|
|||
|
|
@ -868,6 +868,172 @@ def _(o1: Outer1, o2: Outer2, o3: Outer3, o4: Outer4):
|
|||
static_assert(is_subtype_of(Outer4, Outer4))
|
||||
```
|
||||
|
||||
## Structural equivalence
|
||||
|
||||
Two `TypedDict`s with equivalent fields are equivalent types. This includes fields with gradual
|
||||
types:
|
||||
|
||||
```py
|
||||
from typing_extensions import Any, TypedDict, ReadOnly, assert_type
|
||||
from ty_extensions import is_assignable_to, is_equivalent_to, static_assert
|
||||
|
||||
class Foo(TypedDict):
|
||||
x: int
|
||||
y: Any
|
||||
|
||||
# exactly the same fields
|
||||
class Bar(TypedDict):
|
||||
x: int
|
||||
y: Any
|
||||
|
||||
# the same fields but in a different order
|
||||
class Baz(TypedDict):
|
||||
y: Any
|
||||
x: int
|
||||
|
||||
static_assert(is_assignable_to(Foo, Bar))
|
||||
static_assert(is_equivalent_to(Foo, Bar))
|
||||
static_assert(is_assignable_to(Foo, Baz))
|
||||
static_assert(is_equivalent_to(Foo, Baz))
|
||||
|
||||
foo: Foo = {"x": 1, "y": "hello"}
|
||||
assert_type(foo, Foo)
|
||||
assert_type(foo, Bar)
|
||||
assert_type(foo, Baz)
|
||||
```
|
||||
|
||||
Equivalent `TypedDict`s within unions can also produce equivalent unions, which currently relies on
|
||||
"normalization" machinery:
|
||||
|
||||
```py
|
||||
def f(var: Foo | int):
|
||||
assert_type(var, Foo | int)
|
||||
assert_type(var, Bar | int)
|
||||
assert_type(var, Baz | int)
|
||||
# TODO: Union simplification compares `TypedDict`s by name/identity to avoid cycles. This assert
|
||||
# should also pass once that's fixed.
|
||||
assert_type(var, Foo | Bar | Baz | int) # error: [type-assertion-failure]
|
||||
```
|
||||
|
||||
Here are several cases that are not equivalent. In particular, assignability does not imply
|
||||
equivalence:
|
||||
|
||||
```py
|
||||
class FewerFields(TypedDict):
|
||||
x: int
|
||||
|
||||
static_assert(is_assignable_to(Foo, FewerFields))
|
||||
static_assert(not is_equivalent_to(Foo, FewerFields))
|
||||
|
||||
class DifferentMutability(TypedDict):
|
||||
x: int
|
||||
y: ReadOnly[Any]
|
||||
|
||||
static_assert(is_assignable_to(Foo, DifferentMutability))
|
||||
static_assert(not is_equivalent_to(Foo, DifferentMutability))
|
||||
|
||||
class MoreFields(TypedDict):
|
||||
x: int
|
||||
y: Any
|
||||
z: str
|
||||
|
||||
static_assert(not is_assignable_to(Foo, MoreFields))
|
||||
static_assert(not is_equivalent_to(Foo, MoreFields))
|
||||
|
||||
class DifferentFieldStaticType(TypedDict):
|
||||
x: str
|
||||
y: Any
|
||||
|
||||
static_assert(not is_assignable_to(Foo, DifferentFieldStaticType))
|
||||
static_assert(not is_equivalent_to(Foo, DifferentFieldStaticType))
|
||||
|
||||
class DifferentFieldGradualType(TypedDict):
|
||||
x: int
|
||||
y: Any | str
|
||||
|
||||
static_assert(is_assignable_to(Foo, DifferentFieldGradualType))
|
||||
static_assert(not is_equivalent_to(Foo, DifferentFieldGradualType))
|
||||
```
|
||||
|
||||
## Structural equivalence understands the interaction between `Required`/`NotRequired` and `total`
|
||||
|
||||
```py
|
||||
from ty_extensions import static_assert, is_equivalent_to
|
||||
from typing_extensions import TypedDict, Required, NotRequired
|
||||
|
||||
class Foo1(TypedDict, total=False):
|
||||
x: int
|
||||
y: str
|
||||
|
||||
class Foo2(TypedDict):
|
||||
y: NotRequired[str]
|
||||
x: NotRequired[int]
|
||||
|
||||
static_assert(is_equivalent_to(Foo1, Foo2))
|
||||
static_assert(is_equivalent_to(Foo1 | int, int | Foo2))
|
||||
|
||||
class Bar1(TypedDict, total=False):
|
||||
x: int
|
||||
y: Required[str]
|
||||
|
||||
class Bar2(TypedDict):
|
||||
y: str
|
||||
x: NotRequired[int]
|
||||
|
||||
static_assert(is_equivalent_to(Bar1, Bar2))
|
||||
static_assert(is_equivalent_to(Bar1 | int, int | Bar2))
|
||||
```
|
||||
|
||||
## Assignability and equivalence work with recursive `TypedDict`s
|
||||
|
||||
```py
|
||||
from typing_extensions import TypedDict
|
||||
from ty_extensions import static_assert, is_assignable_to, is_equivalent_to
|
||||
|
||||
class Node1(TypedDict):
|
||||
value: int
|
||||
next: "Node1" | None
|
||||
|
||||
class Node2(TypedDict):
|
||||
value: int
|
||||
next: "Node2" | None
|
||||
|
||||
static_assert(is_assignable_to(Node1, Node2))
|
||||
static_assert(is_equivalent_to(Node1, Node2))
|
||||
|
||||
class Person1(TypedDict):
|
||||
name: str
|
||||
friends: list["Person1"]
|
||||
|
||||
class Person2(TypedDict):
|
||||
name: str
|
||||
friends: list["Person2"]
|
||||
|
||||
static_assert(is_assignable_to(Person1, Person2))
|
||||
static_assert(is_equivalent_to(Person1, Person2))
|
||||
```
|
||||
|
||||
## Redundant cast warnings
|
||||
|
||||
<!-- snapshot-diagnostics -->
|
||||
|
||||
Casting between equivalent types produces a redundant cast warning. When the types have different
|
||||
names, the warning makes that clear:
|
||||
|
||||
```py
|
||||
from typing import TypedDict, cast
|
||||
|
||||
class Foo2(TypedDict):
|
||||
x: int
|
||||
|
||||
class Bar2(TypedDict):
|
||||
x: int
|
||||
|
||||
foo: Foo2 = {"x": 1}
|
||||
_ = cast(Foo2, foo) # error: [redundant-cast]
|
||||
_ = cast(Bar2, foo) # error: [redundant-cast]
|
||||
```
|
||||
|
||||
## Key-based access
|
||||
|
||||
### Reading
|
||||
|
|
|
|||
|
|
@ -1268,8 +1268,14 @@ impl<'db> Type<'db> {
|
|||
self.as_union().expect("Expected a Type::Union variant")
|
||||
}
|
||||
|
||||
pub(crate) const fn is_intersection(self) -> bool {
|
||||
matches!(self, Type::Intersection(_))
|
||||
/// Returns whether this is a "real" intersection type. (Negated types are represented by an
|
||||
/// intersection containing a single negative branch, which this method does _not_ consider a
|
||||
/// "real" intersection.)
|
||||
pub(crate) fn is_nontrivial_intersection(self, db: &'db dyn Db) -> bool {
|
||||
match self {
|
||||
Type::Intersection(intersection) => !intersection.is_simple_negation(db),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn as_function_literal(self) -> Option<FunctionType<'db>> {
|
||||
|
|
@ -1465,6 +1471,7 @@ impl<'db> Type<'db> {
|
|||
/// - Strips the types of default values from parameters in `Callable` types: only whether a parameter
|
||||
/// *has* or *does not have* a default value is relevant to whether two `Callable` types are equivalent.
|
||||
/// - Converts class-based protocols into synthesized protocols
|
||||
/// - Converts class-based typeddicts into synthesized typeddicts
|
||||
#[must_use]
|
||||
pub(crate) fn normalized(self, db: &'db dyn Db) -> Self {
|
||||
self.normalized_impl(db, &NormalizedVisitor::default())
|
||||
|
|
@ -1523,10 +1530,9 @@ impl<'db> Type<'db> {
|
|||
// Always normalize single-member enums to their class instance (`Literal[Single.VALUE]` => `Single`)
|
||||
enum_literal.enum_class_instance(db)
|
||||
}
|
||||
Type::TypedDict(_) => {
|
||||
// TODO: Normalize TypedDicts
|
||||
self
|
||||
}
|
||||
Type::TypedDict(typed_dict) => visitor.visit(self, || {
|
||||
Type::TypedDict(typed_dict.normalized_impl(db, visitor))
|
||||
}),
|
||||
Type::TypeAlias(alias) => alias.value_type(db).normalized_impl(db, visitor),
|
||||
Type::NewTypeInstance(newtype) => {
|
||||
visitor.visit(self, || {
|
||||
|
|
@ -3047,6 +3053,10 @@ impl<'db> Type<'db> {
|
|||
left.is_equivalent_to_impl(db, right, inferable, visitor)
|
||||
}
|
||||
|
||||
(Type::TypedDict(left), Type::TypedDict(right)) => visitor.visit((self, other), || {
|
||||
left.is_equivalent_to_impl(db, right, inferable, visitor)
|
||||
}),
|
||||
|
||||
_ => ConstraintSet::from(false),
|
||||
}
|
||||
}
|
||||
|
|
@ -3347,7 +3357,6 @@ impl<'db> Type<'db> {
|
|||
| Type::WrapperDescriptor(..)
|
||||
| Type::ModuleLiteral(..)
|
||||
| Type::ClassLiteral(..)
|
||||
| Type::GenericAlias(..)
|
||||
| Type::SpecialForm(..)
|
||||
| Type::KnownInstance(..)),
|
||||
right @ (Type::BooleanLiteral(..)
|
||||
|
|
@ -3361,7 +3370,6 @@ impl<'db> Type<'db> {
|
|||
| Type::WrapperDescriptor(..)
|
||||
| Type::ModuleLiteral(..)
|
||||
| Type::ClassLiteral(..)
|
||||
| Type::GenericAlias(..)
|
||||
| Type::SpecialForm(..)
|
||||
| Type::KnownInstance(..)),
|
||||
) => ConstraintSet::from(left != right),
|
||||
|
|
@ -3544,13 +3552,39 @@ impl<'db> Type<'db> {
|
|||
ConstraintSet::from(true)
|
||||
}
|
||||
|
||||
(Type::GenericAlias(left_alias), Type::GenericAlias(right_alias)) => {
|
||||
ConstraintSet::from(left_alias.origin(db) != right_alias.origin(db)).or(db, || {
|
||||
left_alias.specialization(db).is_disjoint_from_impl(
|
||||
db,
|
||||
right_alias.specialization(db),
|
||||
inferable,
|
||||
disjointness_visitor,
|
||||
relation_visitor,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
(Type::ClassLiteral(class_literal), other @ Type::GenericAlias(_))
|
||||
| (other @ Type::GenericAlias(_), Type::ClassLiteral(class_literal)) => class_literal
|
||||
.default_specialization(db)
|
||||
.into_generic_alias()
|
||||
.when_none_or(|alias| {
|
||||
other.is_disjoint_from_impl(
|
||||
db,
|
||||
Type::GenericAlias(alias),
|
||||
inferable,
|
||||
disjointness_visitor,
|
||||
relation_visitor,
|
||||
)
|
||||
}),
|
||||
|
||||
(Type::SubclassOf(subclass_of_ty), Type::ClassLiteral(class_b))
|
||||
| (Type::ClassLiteral(class_b), Type::SubclassOf(subclass_of_ty)) => {
|
||||
match subclass_of_ty.subclass_of() {
|
||||
SubclassOfInner::Dynamic(_) => ConstraintSet::from(false),
|
||||
SubclassOfInner::Class(class_a) => {
|
||||
class_b.when_subclass_of(db, None, class_a).negate(db)
|
||||
}
|
||||
SubclassOfInner::Class(class_a) => ConstraintSet::from(
|
||||
!class_a.could_exist_in_mro_of(db, ClassType::NonGeneric(class_b)),
|
||||
),
|
||||
SubclassOfInner::TypeVar(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -3559,9 +3593,9 @@ impl<'db> Type<'db> {
|
|||
| (Type::GenericAlias(alias_b), Type::SubclassOf(subclass_of_ty)) => {
|
||||
match subclass_of_ty.subclass_of() {
|
||||
SubclassOfInner::Dynamic(_) => ConstraintSet::from(false),
|
||||
SubclassOfInner::Class(class_a) => ClassType::from(alias_b)
|
||||
.when_subclass_of(db, class_a, inferable)
|
||||
.negate(db),
|
||||
SubclassOfInner::Class(class_a) => ConstraintSet::from(
|
||||
!class_a.could_exist_in_mro_of(db, ClassType::Generic(alias_b)),
|
||||
),
|
||||
SubclassOfInner::TypeVar(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -3855,6 +3889,8 @@ impl<'db> Type<'db> {
|
|||
relation_visitor,
|
||||
)
|
||||
}
|
||||
|
||||
(Type::GenericAlias(_), _) | (_, Type::GenericAlias(_)) => ConstraintSet::from(true),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7550,7 +7586,13 @@ impl<'db> Type<'db> {
|
|||
Type::ProtocolInstance(protocol) => protocol.to_meta_type(db),
|
||||
// `TypedDict` instances are instances of `dict` at runtime, but its important that we
|
||||
// understand a more specific meta type in order to correctly handle `__getitem__`.
|
||||
Type::TypedDict(typed_dict) => SubclassOfType::from(db, typed_dict.defining_class()),
|
||||
Type::TypedDict(typed_dict) => match typed_dict {
|
||||
TypedDictType::Class(class) => SubclassOfType::from(db, class),
|
||||
TypedDictType::Synthesized(_) => SubclassOfType::from(
|
||||
db,
|
||||
todo_type!("TypedDict synthesized meta-type").expect_dynamic(),
|
||||
),
|
||||
},
|
||||
Type::TypeAlias(alias) => alias.value_type(db).to_meta_type(db),
|
||||
Type::NewTypeInstance(newtype) => Type::from(newtype.base_class_type(db)),
|
||||
}
|
||||
|
|
@ -8259,7 +8301,7 @@ impl<'db> Type<'db> {
|
|||
},
|
||||
|
||||
Self::TypedDict(typed_dict) => {
|
||||
Some(TypeDefinition::Class(typed_dict.defining_class().definition(db)))
|
||||
typed_dict.definition(db).map(TypeDefinition::Class)
|
||||
}
|
||||
|
||||
Self::Union(_) | Self::Intersection(_) => None,
|
||||
|
|
@ -14151,6 +14193,10 @@ impl<'db> IntersectionType<'db> {
|
|||
(self.positive(db).len() + self.negative(db).len()) == 1
|
||||
}
|
||||
|
||||
pub(crate) fn is_simple_negation(self, db: &'db dyn Db) -> bool {
|
||||
self.positive(db).is_empty() && self.negative(db).len() == 1
|
||||
}
|
||||
|
||||
fn heap_size((positive, negative): &(FxOrderSet<Type<'db>>, FxOrderSet<Type<'db>>)) -> usize {
|
||||
ruff_memory_usage::order_set_heap_size(positive)
|
||||
+ ruff_memory_usage::order_set_heap_size(negative)
|
||||
|
|
|
|||
|
|
@ -1911,15 +1911,6 @@ impl<'db> ClassLiteral<'db> {
|
|||
.contains(&ClassBase::Class(other))
|
||||
}
|
||||
|
||||
pub(super) fn when_subclass_of(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
specialization: Option<Specialization<'db>>,
|
||||
other: ClassType<'db>,
|
||||
) -> ConstraintSet<'db> {
|
||||
ConstraintSet::from(self.is_subclass_of(db, specialization, other))
|
||||
}
|
||||
|
||||
/// Return `true` if this class constitutes a typed dict specification (inherits from
|
||||
/// `typing.TypedDict`, either directly or indirectly).
|
||||
#[salsa::tracked(cycle_initial=is_typed_dict_cycle_initial,
|
||||
|
|
|
|||
|
|
@ -435,6 +435,11 @@ impl<'db> ConstraintSet<'db> {
|
|||
pub(crate) fn display(self, db: &'db dyn Db) -> impl Display {
|
||||
self.node.simplify_for_display(db).display(db)
|
||||
}
|
||||
|
||||
#[expect(dead_code)] // Keep this around for debugging purposes
|
||||
pub(crate) fn display_graph(self, db: &'db dyn Db, prefix: &dyn Display) -> impl Display {
|
||||
self.node.display_graph(db, prefix)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for ConstraintSet<'_> {
|
||||
|
|
@ -498,11 +503,13 @@ impl<'db> ConstrainedTypeVar<'db> {
|
|||
debug_assert_eq!(upper, upper.top_materialization(db));
|
||||
|
||||
// It's not useful for an upper bound to be an intersection type, or for a lower bound to
|
||||
// be a union type. Both of those can be rewritten as simpler BDDs:
|
||||
// be a union type. Because the following equivalences hold, we can break these bounds
|
||||
// apart and create an equivalent BDD with more nodes but simpler constraints. (Fewer,
|
||||
// simpler constraints mean that our sequent maps won't grow pathologically large.)
|
||||
//
|
||||
// T ≤ α & β ⇒ (T ≤ α) ∧ (T ≤ β)
|
||||
// T ≤ α & ¬β ⇒ (T ≤ α) ∧ ¬(T ≤ β)
|
||||
// α | β ≤ T ⇒ (α ≤ T) ∧ (β ≤ T)
|
||||
// T ≤ (α & β) ⇔ (T ≤ α) ∧ (T ≤ β)
|
||||
// T ≤ (¬α & ¬β) ⇔ (T ≤ ¬α) ∧ (T ≤ ¬β)
|
||||
// (α | β) ≤ T ⇔ (α ≤ T) ∧ (β ≤ T)
|
||||
if let Type::Union(lower_union) = lower {
|
||||
let mut result = Node::AlwaysTrue;
|
||||
for lower_element in lower_union.elements(db) {
|
||||
|
|
@ -513,7 +520,12 @@ impl<'db> ConstrainedTypeVar<'db> {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
if let Type::Intersection(upper_intersection) = upper {
|
||||
// A negated type ¬α is represented as an intersection with no positive elements, and a
|
||||
// single negative element. We _don't_ want to treat that an "intersection" for the
|
||||
// purposes of simplifying upper bounds.
|
||||
if let Type::Intersection(upper_intersection) = upper
|
||||
&& !upper_intersection.is_simple_negation(db)
|
||||
{
|
||||
let mut result = Node::AlwaysTrue;
|
||||
for upper_element in upper_intersection.iter_positive(db) {
|
||||
result = result.and(
|
||||
|
|
@ -524,7 +536,7 @@ impl<'db> ConstrainedTypeVar<'db> {
|
|||
for upper_element in upper_intersection.iter_negative(db) {
|
||||
result = result.and(
|
||||
db,
|
||||
ConstrainedTypeVar::new_node(db, typevar, lower, upper_element).negate(db),
|
||||
ConstrainedTypeVar::new_node(db, typevar, lower, upper_element.negate(db)),
|
||||
);
|
||||
}
|
||||
return result;
|
||||
|
|
@ -716,7 +728,7 @@ impl<'db> ConstrainedTypeVar<'db> {
|
|||
return IntersectionResult::Disjoint;
|
||||
}
|
||||
|
||||
if lower.is_union() || upper.is_intersection() {
|
||||
if lower.is_union() || upper.is_nontrivial_intersection(db) {
|
||||
return IntersectionResult::CannotSimplify;
|
||||
}
|
||||
|
||||
|
|
@ -1579,7 +1591,6 @@ impl<'db> Node<'db> {
|
|||
/// │ └─₀ never
|
||||
/// └─₀ never
|
||||
/// ```
|
||||
#[cfg_attr(not(test), expect(dead_code))] // Keep this around for debugging purposes
|
||||
fn display_graph(self, db: &'db dyn Db, prefix: &dyn Display) -> impl Display {
|
||||
struct DisplayNode<'a, 'db> {
|
||||
db: &'db dyn Db,
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ use crate::semantic_index::place::{PlaceTable, ScopedPlaceId};
|
|||
use crate::semantic_index::{global_scope, place_table, use_def_map};
|
||||
use crate::suppression::FileSuppressionId;
|
||||
use crate::types::call::CallError;
|
||||
use crate::types::class::{
|
||||
CodeGeneratorKind, DisjointBase, DisjointBaseKind, Field, MethodDecorator,
|
||||
};
|
||||
use crate::types::class::{CodeGeneratorKind, DisjointBase, DisjointBaseKind, MethodDecorator};
|
||||
use crate::types::function::{FunctionDecorators, FunctionType, KnownFunction, OverloadLiteral};
|
||||
use crate::types::infer::UnsupportedComparisonError;
|
||||
use crate::types::overrides::MethodKind;
|
||||
|
|
@ -26,6 +24,7 @@ use crate::types::string_annotation::{
|
|||
RAW_STRING_TYPE_ANNOTATION,
|
||||
};
|
||||
use crate::types::tuple::TupleSpec;
|
||||
use crate::types::typed_dict::TypedDictSchema;
|
||||
use crate::types::{
|
||||
BoundTypeVarInstance, ClassType, DynamicType, LintDiagnosticGuard, Protocol,
|
||||
ProtocolInstanceType, SpecialFormType, SubclassOfInner, Type, TypeContext, binding_type,
|
||||
|
|
@ -3471,7 +3470,7 @@ pub(crate) fn report_invalid_key_on_typed_dict<'db>(
|
|||
typed_dict_ty: Type<'db>,
|
||||
full_object_ty: Option<Type<'db>>,
|
||||
key_ty: Type<'db>,
|
||||
items: &FxIndexMap<Name, Field<'db>>,
|
||||
items: &TypedDictSchema<'db>,
|
||||
) {
|
||||
let db = context.db();
|
||||
if let Some(builder) = context.report_lint(&INVALID_KEY, key_node) {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ use crate::types::visitor::TypeVisitor;
|
|||
use crate::types::{
|
||||
BoundTypeVarIdentity, CallableType, CallableTypeKind, IntersectionType, KnownBoundMethodType,
|
||||
KnownClass, KnownInstanceType, MaterializationKind, Protocol, ProtocolInstanceType,
|
||||
SpecialFormType, StringLiteralType, SubclassOfInner, Type, UnionType, WrapperDescriptorKind,
|
||||
visitor,
|
||||
SpecialFormType, StringLiteralType, SubclassOfInner, Type, TypedDictType, UnionType,
|
||||
WrapperDescriptorKind, visitor,
|
||||
};
|
||||
|
||||
/// Settings for displaying types and signatures
|
||||
|
|
@ -900,12 +900,24 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
|
|||
}
|
||||
f.write_str("]")
|
||||
}
|
||||
Type::TypedDict(typed_dict) => typed_dict
|
||||
.defining_class()
|
||||
Type::TypedDict(TypedDictType::Class(defining_class)) => defining_class
|
||||
.class_literal(self.db)
|
||||
.0
|
||||
.display_with(self.db, self.settings.clone())
|
||||
.fmt_detailed(f),
|
||||
Type::TypedDict(TypedDictType::Synthesized(synthesized)) => {
|
||||
f.set_invalid_syntax();
|
||||
f.write_str("<TypedDict with items ")?;
|
||||
let items = synthesized.items(self.db);
|
||||
for (i, name) in items.keys().enumerate() {
|
||||
let is_last = i == items.len() - 1;
|
||||
write!(f, "'{name}'")?;
|
||||
if !is_last {
|
||||
f.write_str(", ")?;
|
||||
}
|
||||
}
|
||||
f.write_char('>')
|
||||
}
|
||||
Type::TypeAlias(alias) => {
|
||||
f.write_str(alias.name(self.db))?;
|
||||
match alias.specialization(self.db) {
|
||||
|
|
@ -2373,7 +2385,10 @@ mod tests {
|
|||
use crate::Db;
|
||||
use crate::db::tests::setup_db;
|
||||
use crate::place::typing_extensions_symbol;
|
||||
use crate::types::{KnownClass, Parameter, Parameters, Signature, Type};
|
||||
use crate::types::typed_dict::{
|
||||
SynthesizedTypedDictType, TypedDictFieldBuilder, TypedDictSchema,
|
||||
};
|
||||
use crate::types::{KnownClass, Parameter, Parameters, Signature, Type, TypedDictType};
|
||||
|
||||
#[test]
|
||||
fn string_literal_display() {
|
||||
|
|
@ -2418,6 +2433,37 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn synthesized_typeddict_display() {
|
||||
let db = setup_db();
|
||||
|
||||
let mut items = TypedDictSchema::default();
|
||||
items.insert(
|
||||
Name::new("foo"),
|
||||
TypedDictFieldBuilder::new(Type::IntLiteral(42))
|
||||
.required(true)
|
||||
.build(),
|
||||
);
|
||||
items.insert(
|
||||
Name::new("bar"),
|
||||
TypedDictFieldBuilder::new(Type::string_literal(&db, "hello"))
|
||||
.required(true)
|
||||
.build(),
|
||||
);
|
||||
|
||||
let synthesized = SynthesizedTypedDictType::new(&db, items);
|
||||
let type_ = Type::TypedDict(TypedDictType::Synthesized(synthesized));
|
||||
// Fields are sorted internally, even prior to normalization.
|
||||
assert_eq!(
|
||||
type_.display(&db).to_string(),
|
||||
"<TypedDict with items 'bar', 'foo'>",
|
||||
);
|
||||
assert_eq!(
|
||||
type_.normalized(&db).display(&db).to_string(),
|
||||
"<TypedDict with items 'bar', 'foo'>",
|
||||
);
|
||||
}
|
||||
|
||||
fn display_signature<'db>(
|
||||
db: &'db dyn Db,
|
||||
parameters: impl IntoIterator<Item = Parameter<'db>>,
|
||||
|
|
|
|||
|
|
@ -83,8 +83,9 @@ use crate::types::{
|
|||
ApplyTypeMappingVisitor, BoundMethodType, BoundTypeVarInstance, CallableType, CallableTypeKind,
|
||||
ClassBase, ClassLiteral, ClassType, DeprecatedInstance, DynamicType, FindLegacyTypeVarsVisitor,
|
||||
HasRelationToVisitor, IsDisjointVisitor, IsEquivalentVisitor, KnownClass, KnownInstanceType,
|
||||
NormalizedVisitor, SpecialFormType, Truthiness, Type, TypeContext, TypeMapping, TypeRelation,
|
||||
UnionBuilder, binding_type, definition_expression_type, infer_definition_types, walk_signature,
|
||||
NormalizedVisitor, SpecialFormType, SubclassOfInner, SubclassOfType, Truthiness, Type,
|
||||
TypeContext, TypeMapping, TypeRelation, UnionBuilder, binding_type, definition_expression_type,
|
||||
infer_definition_types, walk_signature,
|
||||
};
|
||||
use crate::{Db, FxOrderSet, ModuleName, resolve_module};
|
||||
|
||||
|
|
@ -510,7 +511,7 @@ impl<'db> OverloadLiteral<'db> {
|
|||
|
||||
let generic_context = raw_signature.generic_context;
|
||||
raw_signature.add_implicit_self_annotation(db, || {
|
||||
if self.is_staticmethod(db) || self.is_classmethod(db) {
|
||||
if self.is_staticmethod(db) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -543,19 +544,32 @@ impl<'db> OverloadLiteral<'db> {
|
|||
let index = semantic_index(db, scope_id.file(db));
|
||||
let class = nearest_enclosing_class(db, index, scope_id).unwrap();
|
||||
|
||||
Some(
|
||||
typing_self(db, scope_id, typevar_binding_context, class)
|
||||
.map(Type::TypeVar)
|
||||
.expect(
|
||||
"We should always find the surrounding class \
|
||||
for an implicit self: Self annotation",
|
||||
),
|
||||
)
|
||||
let typing_self = typing_self(db, scope_id, typevar_binding_context, class).expect(
|
||||
"We should always find the surrounding class \
|
||||
for an implicit self: Self annotation",
|
||||
);
|
||||
|
||||
if self.is_classmethod(db) {
|
||||
Some(SubclassOfType::from(
|
||||
db,
|
||||
SubclassOfInner::TypeVar(typing_self),
|
||||
))
|
||||
} else {
|
||||
Some(Type::TypeVar(typing_self))
|
||||
}
|
||||
} else {
|
||||
// For methods of non-generic classes that are not otherwise generic (e.g. return `Self` or
|
||||
// have additional type parameters), the implicit `Self` type of the `self` parameter would
|
||||
// be the only type variable, so we can just use the class directly.
|
||||
Some(class_literal.to_non_generic_instance(db))
|
||||
// have additional type parameters), the implicit `Self` type of the `self`, or the implicit
|
||||
// `type[Self]` type of the `cls` parameter, would be the only type variable, so we can just
|
||||
// use the class directly.
|
||||
if self.is_classmethod(db) {
|
||||
Some(SubclassOfType::from(
|
||||
db,
|
||||
SubclassOfInner::Class(ClassType::NonGeneric(class_literal)),
|
||||
))
|
||||
} else {
|
||||
Some(class_literal.to_non_generic_instance(db))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1082,18 +1096,6 @@ impl<'db> FunctionType<'db> {
|
|||
relation_visitor: &HasRelationToVisitor<'db>,
|
||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||
) -> ConstraintSet<'db> {
|
||||
// A function type is the subtype of itself, and not of any other function type. However,
|
||||
// our representation of a function type includes any specialization that should be applied
|
||||
// to the signature. Different specializations of the same function type are only subtypes
|
||||
// of each other if they result in subtype signatures.
|
||||
if matches!(
|
||||
relation,
|
||||
TypeRelation::Subtyping | TypeRelation::Redundancy | TypeRelation::SubtypingAssuming(_)
|
||||
) && self.normalized(db) == other.normalized(db)
|
||||
{
|
||||
return ConstraintSet::from(true);
|
||||
}
|
||||
|
||||
if self.literal(db) != other.literal(db) {
|
||||
return ConstraintSet::from(false);
|
||||
}
|
||||
|
|
@ -1675,10 +1677,16 @@ impl KnownFunction {
|
|||
&& !any_over_type(db, *casted_type, &contains_unknown_or_todo, true)
|
||||
{
|
||||
if let Some(builder) = context.report_lint(&REDUNDANT_CAST, call_expression) {
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Value is already of type `{}`",
|
||||
casted_type.display(db),
|
||||
let source_display = source_type.display(db).to_string();
|
||||
let casted_display = casted_type.display(db).to_string();
|
||||
let mut diagnostic = builder.into_diagnostic(format_args!(
|
||||
"Value is already of type `{casted_display}`",
|
||||
));
|
||||
if source_display != casted_display {
|
||||
diagnostic.info(format_args!(
|
||||
"`{casted_display}` is equivalent to `{source_display}`",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10850,19 +10850,14 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
(
|
||||
Type::KnownInstance(KnownInstanceType::ConstraintSet(left)),
|
||||
Type::KnownInstance(KnownInstanceType::ConstraintSet(right)),
|
||||
) => {
|
||||
let result = match op {
|
||||
ast::CmpOp::Eq => Some(
|
||||
left.constraints(self.db()).iff(self.db(), right.constraints(self.db()))
|
||||
),
|
||||
ast::CmpOp::NotEq => Some(
|
||||
left.constraints(self.db()).iff(self.db(), right.constraints(self.db())).negate(self.db())
|
||||
),
|
||||
_ => None,
|
||||
};
|
||||
result.map(|constraints| Ok(Type::KnownInstance(KnownInstanceType::ConstraintSet(
|
||||
TrackedConstraintSet::new(self.db(), constraints)
|
||||
))))
|
||||
) => match op {
|
||||
ast::CmpOp::Eq => Some(Ok(Type::BooleanLiteral(
|
||||
left.constraints(self.db()).iff(self.db(), right.constraints(self.db())).is_always_satisfied(self.db()),
|
||||
))),
|
||||
ast::CmpOp::NotEq => Some(Ok(Type::BooleanLiteral(
|
||||
!left.constraints(self.db()).iff(self.db(), right.constraints(self.db())).is_always_satisfied(self.db()),
|
||||
))),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
(
|
||||
|
|
|
|||
|
|
@ -15,9 +15,8 @@ use std::{collections::HashMap, slice::Iter};
|
|||
use itertools::{EitherOrBoth, Itertools};
|
||||
use smallvec::{SmallVec, smallvec_inline};
|
||||
|
||||
use super::{DynamicType, Type, TypeVarVariance, definition_expression_type};
|
||||
use super::{DynamicType, Type, TypeVarVariance, definition_expression_type, semantic_index};
|
||||
use crate::semantic_index::definition::Definition;
|
||||
use crate::semantic_index::semantic_index;
|
||||
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
||||
use crate::types::generics::{GenericContext, InferableTypeVars, walk_generic_context};
|
||||
use crate::types::infer::{infer_deferred_types, infer_scope_types};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use crate::types::{
|
|||
ApplyTypeMappingVisitor, BoundTypeVarInstance, ClassType, DynamicType,
|
||||
FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, KnownClass,
|
||||
MaterializationKind, MemberLookupPolicy, NormalizedVisitor, SpecialFormType, Type, TypeContext,
|
||||
TypeMapping, TypeRelation, TypeVarBoundOrConstraints, todo_type,
|
||||
TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypedDictType, todo_type,
|
||||
};
|
||||
use crate::{Db, FxOrderSet};
|
||||
|
||||
|
|
@ -381,7 +381,12 @@ impl<'db> SubclassOfInner<'db> {
|
|||
pub(crate) fn try_from_instance(db: &'db dyn Db, ty: Type<'db>) -> Option<Self> {
|
||||
Some(match ty {
|
||||
Type::NominalInstance(instance) => SubclassOfInner::Class(instance.class(db)),
|
||||
Type::TypedDict(typed_dict) => SubclassOfInner::Class(typed_dict.defining_class()),
|
||||
Type::TypedDict(typed_dict) => match typed_dict {
|
||||
TypedDictType::Class(class) => SubclassOfInner::Class(class),
|
||||
TypedDictType::Synthesized(_) => SubclassOfInner::Dynamic(
|
||||
todo_type!("type[T] for synthesized TypedDicts").expect_dynamic(),
|
||||
),
|
||||
},
|
||||
Type::TypeVar(bound_typevar) => SubclassOfInner::TypeVar(bound_typevar),
|
||||
Type::Dynamic(DynamicType::Any) => SubclassOfInner::Dynamic(DynamicType::Any),
|
||||
Type::Dynamic(DynamicType::Unknown) => SubclassOfInner::Dynamic(DynamicType::Unknown),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use bitflags::bitflags;
|
||||
use ruff_db::diagnostic::{Annotation, Diagnostic, Span, SubDiagnostic, SubDiagnosticSeverity};
|
||||
use ruff_db::parsed::parsed_module;
|
||||
|
|
@ -12,10 +15,15 @@ use super::diagnostic::{
|
|||
report_missing_typed_dict_key,
|
||||
};
|
||||
use super::{ApplyTypeMappingVisitor, Type, TypeMapping, visitor};
|
||||
use crate::types::constraints::ConstraintSet;
|
||||
use crate::Db;
|
||||
use crate::semantic_index::definition::Definition;
|
||||
use crate::types::class::FieldKind;
|
||||
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
||||
use crate::types::generics::InferableTypeVars;
|
||||
use crate::types::{HasRelationToVisitor, IsDisjointVisitor, TypeContext, TypeRelation};
|
||||
use crate::{Db, FxIndexMap};
|
||||
use crate::types::{
|
||||
HasRelationToVisitor, IsDisjointVisitor, IsEquivalentVisitor, NormalizedVisitor, TypeContext,
|
||||
TypeRelation,
|
||||
};
|
||||
|
||||
use ordermap::OrderSet;
|
||||
|
||||
|
|
@ -41,24 +49,60 @@ impl Default for TypedDictParams {
|
|||
/// Type that represents the set of all inhabitants (`dict` instances) that conform to
|
||||
/// a given `TypedDict` schema.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, salsa::Update, Hash, get_size2::GetSize)]
|
||||
pub struct TypedDictType<'db> {
|
||||
pub enum TypedDictType<'db> {
|
||||
/// A reference to the class (inheriting from `typing.TypedDict`) that specifies the
|
||||
/// schema of this `TypedDict`.
|
||||
defining_class: ClassType<'db>,
|
||||
Class(ClassType<'db>),
|
||||
/// A `TypedDict` that doesn't correspond to a class definition, either because it's been
|
||||
/// `normalized`, or because it's been synthesized to represent constraints.
|
||||
Synthesized(SynthesizedTypedDictType<'db>),
|
||||
}
|
||||
|
||||
impl<'db> TypedDictType<'db> {
|
||||
pub(crate) fn new(defining_class: ClassType<'db>) -> Self {
|
||||
Self { defining_class }
|
||||
Self::Class(defining_class)
|
||||
}
|
||||
|
||||
pub(crate) fn defining_class(self) -> ClassType<'db> {
|
||||
self.defining_class
|
||||
pub(crate) fn defining_class(self) -> Option<ClassType<'db>> {
|
||||
match self {
|
||||
Self::Class(defining_class) => Some(defining_class),
|
||||
Self::Synthesized(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn items(self, db: &'db dyn Db) -> &'db FxIndexMap<Name, Field<'db>> {
|
||||
let (class_literal, specialization) = self.defining_class.class_literal(db);
|
||||
class_literal.fields(db, specialization, CodeGeneratorKind::TypedDict)
|
||||
pub(crate) fn items(self, db: &'db dyn Db) -> &'db TypedDictSchema<'db> {
|
||||
#[salsa::tracked(returns(ref))]
|
||||
fn class_based_items<'db>(db: &'db dyn Db, class: ClassType<'db>) -> TypedDictSchema<'db> {
|
||||
let (class_literal, specialization) = class.class_literal(db);
|
||||
class_literal
|
||||
.fields(db, specialization, CodeGeneratorKind::TypedDict)
|
||||
.into_iter()
|
||||
.map(|(name, field)| {
|
||||
let field = match field {
|
||||
Field {
|
||||
first_declaration,
|
||||
declared_ty,
|
||||
kind:
|
||||
FieldKind::TypedDict {
|
||||
is_required,
|
||||
is_read_only,
|
||||
},
|
||||
} => TypedDictFieldBuilder::new(*declared_ty)
|
||||
.required(*is_required)
|
||||
.read_only(*is_read_only)
|
||||
.first_declaration(*first_declaration)
|
||||
.build(),
|
||||
_ => unreachable!("TypedDict field expected"),
|
||||
};
|
||||
(name.clone(), field)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
match self {
|
||||
Self::Class(defining_class) => class_based_items(db, defining_class),
|
||||
Self::Synthesized(synthesized) => synthesized.items(db),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn apply_type_mapping_impl<'a>(
|
||||
|
|
@ -69,12 +113,12 @@ impl<'db> TypedDictType<'db> {
|
|||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
// TODO: Materialization of gradual TypedDicts needs more logic
|
||||
Self {
|
||||
defining_class: self.defining_class.apply_type_mapping_impl(
|
||||
db,
|
||||
type_mapping,
|
||||
tcx,
|
||||
visitor,
|
||||
match self {
|
||||
Self::Class(defining_class) => {
|
||||
Self::Class(defining_class.apply_type_mapping_impl(db, type_mapping, tcx, visitor))
|
||||
}
|
||||
Self::Synthesized(synthesized) => Self::Synthesized(
|
||||
synthesized.apply_type_mapping_impl(db, type_mapping, tcx, visitor),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
@ -93,9 +137,9 @@ impl<'db> TypedDictType<'db> {
|
|||
// First do a quick nominal check that (if it succeeds) means that we can avoid
|
||||
// materializing the full `TypedDict` schema for either `self` or `target`.
|
||||
// This should be cheaper in many cases, and also helps us avoid some cycles.
|
||||
if self
|
||||
.defining_class
|
||||
.is_subclass_of(db, target.defining_class)
|
||||
if let Some(defining_class) = self.defining_class()
|
||||
&& let Some(target_defining_class) = target.defining_class()
|
||||
&& defining_class.is_subclass_of(db, target_defining_class)
|
||||
{
|
||||
return ConstraintSet::from(true);
|
||||
}
|
||||
|
|
@ -246,6 +290,57 @@ impl<'db> TypedDictType<'db> {
|
|||
}
|
||||
constraints
|
||||
}
|
||||
|
||||
pub fn definition(self, db: &'db dyn Db) -> Option<Definition<'db>> {
|
||||
match self {
|
||||
TypedDictType::Class(defining_class) => Some(defining_class.definition(db)),
|
||||
TypedDictType::Synthesized(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
match self {
|
||||
TypedDictType::Class(_) => {
|
||||
let synthesized = SynthesizedTypedDictType::new(db, self.items(db));
|
||||
TypedDictType::Synthesized(synthesized.normalized_impl(db, visitor))
|
||||
}
|
||||
TypedDictType::Synthesized(synthesized) => {
|
||||
TypedDictType::Synthesized(synthesized.normalized_impl(db, visitor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_equivalent_to_impl(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
other: TypedDictType<'db>,
|
||||
inferable: InferableTypeVars<'_, 'db>,
|
||||
visitor: &IsEquivalentVisitor<'db>,
|
||||
) -> ConstraintSet<'db> {
|
||||
// TODO: `closed` and `extra_items` support will go here. Until then we don't look at the
|
||||
// params at all, because `total` is already incorporated into `FieldKind`.
|
||||
|
||||
// Since both sides' fields are pre-sorted into `BTreeMap`s, we can iterate over them in
|
||||
// sorted order instead of paying for a lookup for each field, as long as their lengths are
|
||||
// the same.
|
||||
if self.items(db).len() != other.items(db).len() {
|
||||
return ConstraintSet::from(false);
|
||||
}
|
||||
self.items(db).iter().zip(other.items(db)).when_all(
|
||||
db,
|
||||
|((name, field), (other_name, other_field))| {
|
||||
if name != other_name || field.flags != other_field.flags {
|
||||
return ConstraintSet::from(false);
|
||||
}
|
||||
field.declared_ty.is_equivalent_to_impl(
|
||||
db,
|
||||
other_field.declared_ty,
|
||||
inferable,
|
||||
visitor,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn walk_typed_dict_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
|
||||
|
|
@ -253,7 +348,16 @@ pub(crate) fn walk_typed_dict_type<'db, V: visitor::TypeVisitor<'db> + ?Sized>(
|
|||
typed_dict: TypedDictType<'db>,
|
||||
visitor: &V,
|
||||
) {
|
||||
visitor.visit_type(db, typed_dict.defining_class.into());
|
||||
match typed_dict {
|
||||
TypedDictType::Class(defining_class) => {
|
||||
visitor.visit_type(db, defining_class.into());
|
||||
}
|
||||
TypedDictType::Synthesized(synthesized) => {
|
||||
for field in synthesized.items(db).values() {
|
||||
visitor.visit_type(db, field.declared_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn typed_dict_params_from_class_def(class_stmt: &StmtClassDef) -> TypedDictParams {
|
||||
|
|
@ -631,3 +735,173 @@ pub(super) fn validate_typed_dict_dict_literal<'db>(
|
|||
Err(provided_keys)
|
||||
}
|
||||
}
|
||||
|
||||
#[salsa::interned(debug)]
|
||||
pub struct SynthesizedTypedDictType<'db> {
|
||||
#[returns(ref)]
|
||||
pub(crate) items: TypedDictSchema<'db>,
|
||||
}
|
||||
|
||||
// The Salsa heap is tracked separately.
|
||||
impl get_size2::GetSize for SynthesizedTypedDictType<'_> {}
|
||||
|
||||
impl<'db> SynthesizedTypedDictType<'db> {
|
||||
pub(super) fn apply_type_mapping_impl<'a>(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
tcx: TypeContext<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
let items = self
|
||||
.items(db)
|
||||
.iter()
|
||||
.map(|(name, field)| {
|
||||
let field = field
|
||||
.clone()
|
||||
.apply_type_mapping_impl(db, type_mapping, tcx, visitor);
|
||||
|
||||
(name.clone(), field)
|
||||
})
|
||||
.collect::<TypedDictSchema<'db>>();
|
||||
|
||||
SynthesizedTypedDictType::new(db, items)
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
let items = self
|
||||
.items(db)
|
||||
.iter()
|
||||
.map(|(name, field)| {
|
||||
let field = field.clone().normalized_impl(db, visitor);
|
||||
(name.clone(), field)
|
||||
})
|
||||
.collect::<TypedDictSchema<'db>>();
|
||||
Self::new(db, items)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, get_size2::GetSize, salsa::Update)]
|
||||
pub struct TypedDictSchema<'db>(BTreeMap<Name, TypedDictField<'db>>);
|
||||
|
||||
impl<'db> Deref for TypedDictSchema<'db> {
|
||||
type Target = BTreeMap<Name, TypedDictField<'db>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for TypedDictSchema<'_> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a TypedDictSchema<'_> {
|
||||
type Item = (&'a Name, &'a TypedDictField<'a>);
|
||||
type IntoIter = std::collections::btree_map::Iter<'a, Name, TypedDictField<'a>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> FromIterator<(Name, TypedDictField<'db>)> for TypedDictSchema<'db> {
|
||||
fn from_iter<T: IntoIterator<Item = (Name, TypedDictField<'db>)>>(iter: T) -> Self {
|
||||
Self(iter.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize, salsa::Update)]
|
||||
pub struct TypedDictField<'db> {
|
||||
pub(super) declared_ty: Type<'db>,
|
||||
flags: TypedDictFieldFlags,
|
||||
first_declaration: Option<Definition<'db>>,
|
||||
}
|
||||
|
||||
impl<'db> TypedDictField<'db> {
|
||||
pub(crate) const fn is_required(&self) -> bool {
|
||||
self.flags.contains(TypedDictFieldFlags::REQUIRED)
|
||||
}
|
||||
|
||||
pub(crate) const fn is_read_only(&self) -> bool {
|
||||
self.flags.contains(TypedDictFieldFlags::READ_ONLY)
|
||||
}
|
||||
|
||||
pub(crate) fn apply_type_mapping_impl<'a>(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
type_mapping: &TypeMapping<'a, 'db>,
|
||||
tcx: TypeContext<'db>,
|
||||
visitor: &ApplyTypeMappingVisitor<'db>,
|
||||
) -> Self {
|
||||
Self {
|
||||
declared_ty: self
|
||||
.declared_ty
|
||||
.apply_type_mapping_impl(db, type_mapping, tcx, visitor),
|
||||
flags: self.flags,
|
||||
first_declaration: self.first_declaration,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn normalized_impl(self, db: &'db dyn Db, visitor: &NormalizedVisitor<'db>) -> Self {
|
||||
Self {
|
||||
declared_ty: self.declared_ty.normalized_impl(db, visitor),
|
||||
flags: self.flags,
|
||||
// A normalized typed-dict field does not hold onto the original declaration,
|
||||
// since a normalized typed-dict is an abstract type where equality does not depend
|
||||
// on the source-code definition.
|
||||
first_declaration: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct TypedDictFieldBuilder<'db> {
|
||||
declared_ty: Type<'db>,
|
||||
flags: TypedDictFieldFlags,
|
||||
first_declaration: Option<Definition<'db>>,
|
||||
}
|
||||
|
||||
impl<'db> TypedDictFieldBuilder<'db> {
|
||||
pub(crate) fn new(declared_ty: Type<'db>) -> Self {
|
||||
Self {
|
||||
declared_ty,
|
||||
flags: TypedDictFieldFlags::empty(),
|
||||
first_declaration: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn required(mut self, yes: bool) -> Self {
|
||||
self.flags.set(TypedDictFieldFlags::REQUIRED, yes);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn read_only(mut self, yes: bool) -> Self {
|
||||
self.flags.set(TypedDictFieldFlags::READ_ONLY, yes);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn first_declaration(mut self, definition: Option<Definition<'db>>) -> Self {
|
||||
self.first_declaration = definition;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn build(self) -> TypedDictField<'db> {
|
||||
TypedDictField {
|
||||
declared_ty: self.declared_ty,
|
||||
flags: self.flags,
|
||||
first_declaration: self.first_declaration,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)]
|
||||
struct TypedDictFieldFlags: u8 {
|
||||
const REQUIRED = 1 << 0;
|
||||
const READ_ONLY = 1 << 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl get_size2::GetSize for TypedDictFieldFlags {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue