mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 13:51:37 +00:00
[ty] Split Type::KnownInstance
into two type variants (#18350)
This commit is contained in:
parent
aee3af0f7a
commit
47a2ec002e
14 changed files with 830 additions and 784 deletions
108
crates/ty/docs/rules.md
generated
108
crates/ty/docs/rules.md
generated
|
@ -52,7 +52,7 @@ Calling a non-callable object will raise a `TypeError` at runtime.
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20call-non-callable)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20call-non-callable)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L93)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L92)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `conflicting-argument-forms`
|
## `conflicting-argument-forms`
|
||||||
|
@ -83,7 +83,7 @@ f(int) # error
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-argument-forms)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-argument-forms)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L137)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L136)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `conflicting-declarations`
|
## `conflicting-declarations`
|
||||||
|
@ -113,7 +113,7 @@ a = 1
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-declarations)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-declarations)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L163)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L162)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `conflicting-metaclass`
|
## `conflicting-metaclass`
|
||||||
|
@ -144,7 +144,7 @@ class C(A, B): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-metaclass)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-metaclass)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L188)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L187)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `cyclic-class-definition`
|
## `cyclic-class-definition`
|
||||||
|
@ -175,7 +175,7 @@ class B(A): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20cyclic-class-definition)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20cyclic-class-definition)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L214)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L213)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `duplicate-base`
|
## `duplicate-base`
|
||||||
|
@ -201,7 +201,7 @@ class B(A, A): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20duplicate-base)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20duplicate-base)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L258)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L257)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `escape-character-in-forward-annotation`
|
## `escape-character-in-forward-annotation`
|
||||||
|
@ -338,7 +338,7 @@ TypeError: multiple bases have instance lay-out conflict
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20incompatible-slots)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20incompatible-slots)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L279)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L278)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `inconsistent-mro`
|
## `inconsistent-mro`
|
||||||
|
@ -367,7 +367,7 @@ class C(A, B): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20inconsistent-mro)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20inconsistent-mro)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L365)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L364)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `index-out-of-bounds`
|
## `index-out-of-bounds`
|
||||||
|
@ -392,7 +392,7 @@ t[3] # IndexError: tuple index out of range
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20index-out-of-bounds)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20index-out-of-bounds)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L389)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L388)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-argument-type`
|
## `invalid-argument-type`
|
||||||
|
@ -418,7 +418,7 @@ func("foo") # error: [invalid-argument-type]
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-argument-type)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-argument-type)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L409)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L408)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-assignment`
|
## `invalid-assignment`
|
||||||
|
@ -445,7 +445,7 @@ a: int = ''
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-assignment)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-assignment)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L449)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L448)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-attribute-access`
|
## `invalid-attribute-access`
|
||||||
|
@ -478,7 +478,7 @@ C.instance_var = 3 # error: Cannot assign to instance variable
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-attribute-access)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-attribute-access)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1397)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1396)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-base`
|
## `invalid-base`
|
||||||
|
@ -501,7 +501,7 @@ class A(42): ... # error: [invalid-base]
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-base)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-base)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L471)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L470)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-context-manager`
|
## `invalid-context-manager`
|
||||||
|
@ -527,7 +527,7 @@ with 1:
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-context-manager)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-context-manager)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L522)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L521)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-declaration`
|
## `invalid-declaration`
|
||||||
|
@ -555,7 +555,7 @@ a: str
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-declaration)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-declaration)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L543)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L542)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-exception-caught`
|
## `invalid-exception-caught`
|
||||||
|
@ -596,7 +596,7 @@ except ZeroDivisionError:
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-exception-caught)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-exception-caught)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L566)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L565)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-generic-class`
|
## `invalid-generic-class`
|
||||||
|
@ -627,7 +627,7 @@ class C[U](Generic[T]): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-generic-class)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-generic-class)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L602)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L601)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-legacy-type-variable`
|
## `invalid-legacy-type-variable`
|
||||||
|
@ -660,7 +660,7 @@ def f(t: TypeVar("U")): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-legacy-type-variable)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-legacy-type-variable)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L628)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L627)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-metaclass`
|
## `invalid-metaclass`
|
||||||
|
@ -692,7 +692,7 @@ class B(metaclass=f): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-metaclass)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-metaclass)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L677)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L676)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-overload`
|
## `invalid-overload`
|
||||||
|
@ -740,7 +740,7 @@ def foo(x: int) -> int: ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-overload)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-overload)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L704)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L703)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-parameter-default`
|
## `invalid-parameter-default`
|
||||||
|
@ -765,7 +765,7 @@ def f(a: int = ''): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-parameter-default)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-parameter-default)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L747)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L746)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-protocol`
|
## `invalid-protocol`
|
||||||
|
@ -798,7 +798,7 @@ TypeError: Protocols can only inherit from other protocols, got <class 'int'>
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-protocol)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-protocol)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L337)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L336)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-raise`
|
## `invalid-raise`
|
||||||
|
@ -846,7 +846,7 @@ def g():
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-raise)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-raise)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L767)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L766)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-return-type`
|
## `invalid-return-type`
|
||||||
|
@ -870,7 +870,7 @@ def func() -> int:
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-return-type)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-return-type)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L430)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L429)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-super-argument`
|
## `invalid-super-argument`
|
||||||
|
@ -914,7 +914,7 @@ super(B, A) # error: `A` does not satisfy `issubclass(A, B)`
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-super-argument)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-super-argument)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L810)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L809)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-syntax-in-forward-annotation`
|
## `invalid-syntax-in-forward-annotation`
|
||||||
|
@ -954,7 +954,7 @@ NewAlias = TypeAliasType(get_name(), int) # error: TypeAliasType name mus
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-alias-type)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-alias-type)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L656)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L655)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-type-checking-constant`
|
## `invalid-type-checking-constant`
|
||||||
|
@ -983,7 +983,7 @@ TYPE_CHECKING = ''
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-checking-constant)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-checking-constant)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L849)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L848)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-type-form`
|
## `invalid-type-form`
|
||||||
|
@ -1012,7 +1012,7 @@ b: Annotated[int] # `Annotated` expects at least two arguments
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-form)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-form)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L873)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L872)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-type-variable-constraints`
|
## `invalid-type-variable-constraints`
|
||||||
|
@ -1046,7 +1046,7 @@ T = TypeVar('T', bound=str) # valid bound TypeVar
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-variable-constraints)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-variable-constraints)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L897)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L896)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `missing-argument`
|
## `missing-argument`
|
||||||
|
@ -1070,7 +1070,7 @@ func() # TypeError: func() missing 1 required positional argument: 'x'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20missing-argument)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20missing-argument)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L926)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L925)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `no-matching-overload`
|
## `no-matching-overload`
|
||||||
|
@ -1098,7 +1098,7 @@ func("string") # error: [no-matching-overload]
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20no-matching-overload)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20no-matching-overload)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L945)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L944)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `non-subscriptable`
|
## `non-subscriptable`
|
||||||
|
@ -1121,7 +1121,7 @@ Subscripting an object that does not support it will raise a `TypeError` at runt
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20non-subscriptable)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20non-subscriptable)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L968)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L967)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `not-iterable`
|
## `not-iterable`
|
||||||
|
@ -1146,7 +1146,7 @@ for i in 34: # TypeError: 'int' object is not iterable
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20not-iterable)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20not-iterable)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L986)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L985)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `parameter-already-assigned`
|
## `parameter-already-assigned`
|
||||||
|
@ -1172,7 +1172,7 @@ f(1, x=2) # Error raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20parameter-already-assigned)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20parameter-already-assigned)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1037)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1036)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `raw-string-type-annotation`
|
## `raw-string-type-annotation`
|
||||||
|
@ -1231,7 +1231,7 @@ static_assert(int(2.0 * 3.0) == 6) # error: does not have a statically known tr
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20static-assert-error)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20static-assert-error)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1373)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1372)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `subclass-of-final-class`
|
## `subclass-of-final-class`
|
||||||
|
@ -1259,7 +1259,7 @@ class B(A): ... # Error raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20subclass-of-final-class)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20subclass-of-final-class)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1128)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1127)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `too-many-positional-arguments`
|
## `too-many-positional-arguments`
|
||||||
|
@ -1285,7 +1285,7 @@ f("foo") # Error raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20too-many-positional-arguments)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20too-many-positional-arguments)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1173)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1172)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `type-assertion-failure`
|
## `type-assertion-failure`
|
||||||
|
@ -1312,7 +1312,7 @@ def _(x: int):
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20type-assertion-failure)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20type-assertion-failure)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1151)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1150)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unavailable-implicit-super-arguments`
|
## `unavailable-implicit-super-arguments`
|
||||||
|
@ -1356,7 +1356,7 @@ class A:
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unavailable-implicit-super-arguments)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unavailable-implicit-super-arguments)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1194)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1193)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unknown-argument`
|
## `unknown-argument`
|
||||||
|
@ -1382,7 +1382,7 @@ f(x=1, y=2) # Error raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unknown-argument)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unknown-argument)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1251)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1250)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unresolved-attribute`
|
## `unresolved-attribute`
|
||||||
|
@ -1409,7 +1409,7 @@ A().foo # AttributeError: 'A' object has no attribute 'foo'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-attribute)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-attribute)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1272)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1271)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unresolved-import`
|
## `unresolved-import`
|
||||||
|
@ -1433,7 +1433,7 @@ import foo # ModuleNotFoundError: No module named 'foo'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-import)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-import)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1294)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1293)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unresolved-reference`
|
## `unresolved-reference`
|
||||||
|
@ -1457,7 +1457,7 @@ print(x) # NameError: name 'x' is not defined
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-reference)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-reference)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1313)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1312)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unsupported-bool-conversion`
|
## `unsupported-bool-conversion`
|
||||||
|
@ -1493,7 +1493,7 @@ b1 < b2 < b1 # exception raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-bool-conversion)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-bool-conversion)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1006)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1005)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unsupported-operator`
|
## `unsupported-operator`
|
||||||
|
@ -1520,7 +1520,7 @@ A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-operator)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-operator)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1332)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1331)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `zero-stepsize-in-slice`
|
## `zero-stepsize-in-slice`
|
||||||
|
@ -1544,7 +1544,7 @@ l[1:10:0] # ValueError: slice step cannot be zero
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20zero-stepsize-in-slice)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20zero-stepsize-in-slice)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1354)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1353)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-ignore-comment`
|
## `invalid-ignore-comment`
|
||||||
|
@ -1600,7 +1600,7 @@ A.c # AttributeError: type object 'A' has no attribute 'c'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-attribute)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-attribute)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1058)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1057)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `possibly-unbound-implicit-call`
|
## `possibly-unbound-implicit-call`
|
||||||
|
@ -1631,7 +1631,7 @@ A()[0] # TypeError: 'A' object is not subscriptable
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-implicit-call)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-implicit-call)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L111)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L110)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `possibly-unbound-import`
|
## `possibly-unbound-import`
|
||||||
|
@ -1662,7 +1662,7 @@ from module import a # ImportError: cannot import name 'a' from 'module'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-import)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-import)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1080)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1079)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `redundant-cast`
|
## `redundant-cast`
|
||||||
|
@ -1688,7 +1688,7 @@ cast(int, f()) # Redundant
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20redundant-cast)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20redundant-cast)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1425)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1424)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `undefined-reveal`
|
## `undefined-reveal`
|
||||||
|
@ -1711,7 +1711,7 @@ reveal_type(1) # NameError: name 'reveal_type' is not defined
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20undefined-reveal)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20undefined-reveal)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1233)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1232)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unknown-rule`
|
## `unknown-rule`
|
||||||
|
@ -1779,7 +1779,7 @@ class D(C): ... # error: [unsupported-base]
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-base)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-base)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L489)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L488)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `division-by-zero`
|
## `division-by-zero`
|
||||||
|
@ -1802,7 +1802,7 @@ Dividing by zero raises a `ZeroDivisionError` at runtime.
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20division-by-zero)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20division-by-zero)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L240)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L239)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `possibly-unresolved-reference`
|
## `possibly-unresolved-reference`
|
||||||
|
@ -1829,7 +1829,7 @@ print(x) # NameError: name 'x' is not defined
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unresolved-reference)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unresolved-reference)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1106)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1105)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unused-ignore-comment`
|
## `unused-ignore-comment`
|
||||||
|
|
|
@ -1131,7 +1131,7 @@ fn widen_type_for_undeclared_public_symbol<'db>(
|
||||||
// such.
|
// such.
|
||||||
let is_known_instance = inferred
|
let is_known_instance = inferred
|
||||||
.ignore_possibly_unbound()
|
.ignore_possibly_unbound()
|
||||||
.is_some_and(|ty| matches!(ty, Type::KnownInstance(_)));
|
.is_some_and(|ty| matches!(ty, Type::SpecialForm(_) | Type::KnownInstance(_)));
|
||||||
|
|
||||||
if is_considered_non_modifiable || is_known_instance {
|
if is_considered_non_modifiable || is_known_instance {
|
||||||
inferred
|
inferred
|
||||||
|
|
|
@ -54,8 +54,8 @@ pub use crate::util::diagnostics::add_inferred_python_version_hint_to_diagnostic
|
||||||
use crate::{Db, FxOrderSet, Module, Program};
|
use crate::{Db, FxOrderSet, Module, Program};
|
||||||
pub(crate) use class::{ClassLiteral, ClassType, GenericAlias, KnownClass};
|
pub(crate) use class::{ClassLiteral, ClassType, GenericAlias, KnownClass};
|
||||||
use instance::Protocol;
|
use instance::Protocol;
|
||||||
pub(crate) use instance::{NominalInstanceType, ProtocolInstanceType};
|
pub use instance::{NominalInstanceType, ProtocolInstanceType};
|
||||||
pub(crate) use known_instance::KnownInstanceType;
|
pub use special_form::SpecialFormType;
|
||||||
|
|
||||||
mod builder;
|
mod builder;
|
||||||
mod call;
|
mod call;
|
||||||
|
@ -67,12 +67,12 @@ mod display;
|
||||||
mod generics;
|
mod generics;
|
||||||
mod infer;
|
mod infer;
|
||||||
mod instance;
|
mod instance;
|
||||||
mod known_instance;
|
|
||||||
mod mro;
|
mod mro;
|
||||||
mod narrow;
|
mod narrow;
|
||||||
mod protocol_class;
|
mod protocol_class;
|
||||||
mod signatures;
|
mod signatures;
|
||||||
mod slots;
|
mod slots;
|
||||||
|
mod special_form;
|
||||||
mod string_annotation;
|
mod string_annotation;
|
||||||
mod subclass_of;
|
mod subclass_of;
|
||||||
mod type_ordering;
|
mod type_ordering;
|
||||||
|
@ -511,7 +511,12 @@ pub enum Type<'db> {
|
||||||
/// The set of Python objects that conform to the interface described by a given protocol.
|
/// The set of Python objects that conform to the interface described by a given protocol.
|
||||||
/// Construct this variant using the `Type::instance` constructor function.
|
/// Construct this variant using the `Type::instance` constructor function.
|
||||||
ProtocolInstance(ProtocolInstanceType<'db>),
|
ProtocolInstance(ProtocolInstanceType<'db>),
|
||||||
/// A single Python object that requires special treatment in the type system
|
/// A single Python object that requires special treatment in the type system,
|
||||||
|
/// and which exists at a location that can be known prior to any analysis by ty.
|
||||||
|
SpecialForm(SpecialFormType),
|
||||||
|
/// Singleton types that are heavily special-cased by ty, and which are usually
|
||||||
|
/// created as a result of some runtime operation (e.g. a type-alias statement,
|
||||||
|
/// a typevar definition, or `Generic[T]` in a class's bases list).
|
||||||
KnownInstance(KnownInstanceType<'db>),
|
KnownInstance(KnownInstanceType<'db>),
|
||||||
/// An instance of `builtins.property`
|
/// An instance of `builtins.property`
|
||||||
PropertyInstance(PropertyInstanceType<'db>),
|
PropertyInstance(PropertyInstanceType<'db>),
|
||||||
|
@ -664,6 +669,7 @@ impl<'db> Type<'db> {
|
||||||
| Self::ModuleLiteral(_)
|
| Self::ModuleLiteral(_)
|
||||||
| Self::ClassLiteral(_)
|
| Self::ClassLiteral(_)
|
||||||
| Self::NominalInstance(_)
|
| Self::NominalInstance(_)
|
||||||
|
| Self::SpecialForm(_)
|
||||||
| Self::KnownInstance(_)
|
| Self::KnownInstance(_)
|
||||||
| Self::PropertyInstance(_)
|
| Self::PropertyInstance(_)
|
||||||
| Self::BoundMethod(_)
|
| Self::BoundMethod(_)
|
||||||
|
@ -691,6 +697,7 @@ impl<'db> Type<'db> {
|
||||||
| Self::ModuleLiteral(_)
|
| Self::ModuleLiteral(_)
|
||||||
| Self::FunctionLiteral(_)
|
| Self::FunctionLiteral(_)
|
||||||
| Self::ClassLiteral(_)
|
| Self::ClassLiteral(_)
|
||||||
|
| Self::SpecialForm(_)
|
||||||
| Self::KnownInstance(_)
|
| Self::KnownInstance(_)
|
||||||
| Self::StringLiteral(_)
|
| Self::StringLiteral(_)
|
||||||
| Self::IntLiteral(_)
|
| Self::IntLiteral(_)
|
||||||
|
@ -936,19 +943,6 @@ impl<'db> Type<'db> {
|
||||||
.expect("Expected a Type::IntLiteral variant")
|
.expect("Expected a Type::IntLiteral variant")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn into_known_instance(self) -> Option<KnownInstanceType<'db>> {
|
|
||||||
match self {
|
|
||||||
Type::KnownInstance(known_instance) => Some(known_instance),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub fn expect_known_instance(self) -> KnownInstanceType<'db> {
|
|
||||||
self.into_known_instance()
|
|
||||||
.expect("Expected a Type::KnownInstance variant")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn into_tuple(self) -> Option<TupleType<'db>> {
|
pub const fn into_tuple(self) -> Option<TupleType<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Type::Tuple(tuple_type) => Some(tuple_type),
|
Type::Tuple(tuple_type) => Some(tuple_type),
|
||||||
|
@ -1042,6 +1036,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::DataclassTransformer(_)
|
| Type::DataclassTransformer(_)
|
||||||
| Type::ModuleLiteral(_)
|
| Type::ModuleLiteral(_)
|
||||||
| Type::ClassLiteral(_)
|
| Type::ClassLiteral(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::IntLiteral(_) => self,
|
| Type::IntLiteral(_) => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1385,9 +1380,11 @@ impl<'db> Type<'db> {
|
||||||
metaclass_instance_type.is_subtype_of(db, target)
|
metaclass_instance_type.is_subtype_of(db, target)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// For example: `Type::KnownInstance(KnownInstanceType::Type)` is a subtype of `Type::NominalInstance(_SpecialForm)`,
|
// For example: `Type::SpecialForm(SpecialFormType::Type)` is a subtype of `Type::NominalInstance(_SpecialForm)`,
|
||||||
// because `Type::KnownInstance(KnownInstanceType::Type)` is a set with exactly one runtime value in it
|
// because `Type::SpecialForm(SpecialFormType::Type)` is a set with exactly one runtime value in it
|
||||||
// (the symbol `typing.Type`), and that symbol is known to be an instance of `typing._SpecialForm` at runtime.
|
// (the symbol `typing.Type`), and that symbol is known to be an instance of `typing._SpecialForm` at runtime.
|
||||||
|
(Type::SpecialForm(left), right) => left.instance_fallback(db).is_subtype_of(db, right),
|
||||||
|
|
||||||
(Type::KnownInstance(left), right) => {
|
(Type::KnownInstance(left), right) => {
|
||||||
left.instance_fallback(db).is_subtype_of(db, right)
|
left.instance_fallback(db).is_subtype_of(db, right)
|
||||||
}
|
}
|
||||||
|
@ -1884,6 +1881,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::ModuleLiteral(..)
|
| Type::ModuleLiteral(..)
|
||||||
| Type::ClassLiteral(..)
|
| Type::ClassLiteral(..)
|
||||||
| Type::GenericAlias(..)
|
| Type::GenericAlias(..)
|
||||||
|
| Type::SpecialForm(..)
|
||||||
| Type::KnownInstance(..)),
|
| Type::KnownInstance(..)),
|
||||||
right @ (Type::BooleanLiteral(..)
|
right @ (Type::BooleanLiteral(..)
|
||||||
| Type::IntLiteral(..)
|
| Type::IntLiteral(..)
|
||||||
|
@ -1896,6 +1894,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::ModuleLiteral(..)
|
| Type::ModuleLiteral(..)
|
||||||
| Type::ClassLiteral(..)
|
| Type::ClassLiteral(..)
|
||||||
| Type::GenericAlias(..)
|
| Type::GenericAlias(..)
|
||||||
|
| Type::SpecialForm(..)
|
||||||
| Type::KnownInstance(..)),
|
| Type::KnownInstance(..)),
|
||||||
) => left != right,
|
) => left != right,
|
||||||
|
|
||||||
|
@ -2028,6 +2027,11 @@ impl<'db> Type<'db> {
|
||||||
| Type::IntLiteral(..)),
|
| Type::IntLiteral(..)),
|
||||||
) => !ty.satisfies_protocol(db, protocol),
|
) => !ty.satisfies_protocol(db, protocol),
|
||||||
|
|
||||||
|
(Type::ProtocolInstance(protocol), Type::SpecialForm(special_form))
|
||||||
|
| (Type::SpecialForm(special_form), Type::ProtocolInstance(protocol)) => !special_form
|
||||||
|
.instance_fallback(db)
|
||||||
|
.satisfies_protocol(db, protocol),
|
||||||
|
|
||||||
(Type::ProtocolInstance(protocol), Type::KnownInstance(known_instance))
|
(Type::ProtocolInstance(protocol), Type::KnownInstance(known_instance))
|
||||||
| (Type::KnownInstance(known_instance), Type::ProtocolInstance(protocol)) => {
|
| (Type::KnownInstance(known_instance), Type::ProtocolInstance(protocol)) => {
|
||||||
!known_instance
|
!known_instance
|
||||||
|
@ -2063,15 +2067,24 @@ impl<'db> Type<'db> {
|
||||||
.is_disjoint_from(db, other),
|
.is_disjoint_from(db, other),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
(Type::SpecialForm(special_form), Type::NominalInstance(instance))
|
||||||
|
| (Type::NominalInstance(instance), Type::SpecialForm(special_form)) => {
|
||||||
|
!special_form.is_instance_of(db, instance.class)
|
||||||
|
}
|
||||||
|
|
||||||
(Type::KnownInstance(known_instance), Type::NominalInstance(instance))
|
(Type::KnownInstance(known_instance), Type::NominalInstance(instance))
|
||||||
| (Type::NominalInstance(instance), Type::KnownInstance(known_instance)) => {
|
| (Type::NominalInstance(instance), Type::KnownInstance(known_instance)) => {
|
||||||
!known_instance.is_instance_of(db, instance.class)
|
!known_instance.is_instance_of(db, instance.class)
|
||||||
}
|
}
|
||||||
|
|
||||||
(known_instance_ty @ Type::KnownInstance(_), Type::Tuple(tuple))
|
(
|
||||||
| (Type::Tuple(tuple), known_instance_ty @ Type::KnownInstance(_)) => {
|
known_instance_ty @ (Type::SpecialForm(_) | Type::KnownInstance(_)),
|
||||||
known_instance_ty.is_disjoint_from(db, tuple.homogeneous_supertype(db))
|
Type::Tuple(tuple),
|
||||||
}
|
)
|
||||||
|
| (
|
||||||
|
Type::Tuple(tuple),
|
||||||
|
known_instance_ty @ (Type::SpecialForm(_) | Type::KnownInstance(_)),
|
||||||
|
) => known_instance_ty.is_disjoint_from(db, tuple.homogeneous_supertype(db)),
|
||||||
|
|
||||||
(Type::BooleanLiteral(..), Type::NominalInstance(instance))
|
(Type::BooleanLiteral(..), Type::NominalInstance(instance))
|
||||||
| (Type::NominalInstance(instance), Type::BooleanLiteral(..)) => {
|
| (Type::NominalInstance(instance), Type::BooleanLiteral(..)) => {
|
||||||
|
@ -2231,6 +2244,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::StringLiteral(_)
|
| Type::StringLiteral(_)
|
||||||
| Type::LiteralString
|
| Type::LiteralString
|
||||||
| Type::BytesLiteral(_)
|
| Type::BytesLiteral(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::KnownInstance(_)
|
| Type::KnownInstance(_)
|
||||||
| Type::AlwaysFalsy
|
| Type::AlwaysFalsy
|
||||||
| Type::AlwaysTruthy
|
| Type::AlwaysTruthy
|
||||||
|
@ -2345,15 +2359,16 @@ impl<'db> Type<'db> {
|
||||||
| Type::ClassLiteral(..)
|
| Type::ClassLiteral(..)
|
||||||
| Type::GenericAlias(..)
|
| Type::GenericAlias(..)
|
||||||
| Type::ModuleLiteral(..) => true,
|
| Type::ModuleLiteral(..) => true,
|
||||||
Type::KnownInstance(known_instance) => {
|
Type::SpecialForm(special_form) => {
|
||||||
// Nearly all `KnownInstance` types are singletons, but if a symbol could validly
|
// Nearly all `SpecialForm` types are singletons, but if a symbol could validly
|
||||||
// originate from either `typing` or `typing_extensions` then this is not guaranteed.
|
// originate from either `typing` or `typing_extensions` then this is not guaranteed.
|
||||||
// E.g. `typing.Protocol` is equivalent to `typing_extensions.Protocol`, so both are treated
|
// E.g. `typing.TypeGuard` is equivalent to `typing_extensions.TypeGuard`, so both are treated
|
||||||
// as inhabiting the type `KnownInstanceType::Protocol` in our model, but they are actually
|
// as inhabiting the type `SpecialFormType::TypeGuard` in our model, but they are actually
|
||||||
// distinct symbols at different memory addresses at runtime.
|
// distinct symbols at different memory addresses at runtime.
|
||||||
!(known_instance.check_module(KnownModule::Typing)
|
!(special_form.check_module(KnownModule::Typing)
|
||||||
&& known_instance.check_module(KnownModule::TypingExtensions))
|
&& special_form.check_module(KnownModule::TypingExtensions))
|
||||||
}
|
}
|
||||||
|
Type::KnownInstance(_) => false,
|
||||||
Type::Callable(_) => {
|
Type::Callable(_) => {
|
||||||
// A callable type is never a singleton because for any given signature,
|
// A callable type is never a singleton because for any given signature,
|
||||||
// there could be any number of distinct objects that are all callable with that
|
// there could be any number of distinct objects that are all callable with that
|
||||||
|
@ -2421,6 +2436,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::BooleanLiteral(..)
|
| Type::BooleanLiteral(..)
|
||||||
| Type::StringLiteral(..)
|
| Type::StringLiteral(..)
|
||||||
| Type::BytesLiteral(..)
|
| Type::BytesLiteral(..)
|
||||||
|
| Type::SpecialForm(..)
|
||||||
| Type::KnownInstance(..) => true,
|
| Type::KnownInstance(..) => true,
|
||||||
|
|
||||||
Type::ProtocolInstance(..) => {
|
Type::ProtocolInstance(..) => {
|
||||||
|
@ -2575,6 +2591,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::DataclassDecorator(_)
|
| Type::DataclassDecorator(_)
|
||||||
| Type::DataclassTransformer(_)
|
| Type::DataclassTransformer(_)
|
||||||
| Type::ModuleLiteral(_)
|
| Type::ModuleLiteral(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::KnownInstance(_)
|
| Type::KnownInstance(_)
|
||||||
| Type::AlwaysTruthy
|
| Type::AlwaysTruthy
|
||||||
| Type::AlwaysFalsy
|
| Type::AlwaysFalsy
|
||||||
|
@ -2699,7 +2716,7 @@ impl<'db> Type<'db> {
|
||||||
.to_instance(db)
|
.to_instance(db)
|
||||||
.instance_member(db, name),
|
.instance_member(db, name),
|
||||||
|
|
||||||
Type::KnownInstance(_) => Symbol::Unbound.into(),
|
Type::SpecialForm(_) | Type::KnownInstance(_) => Symbol::Unbound.into(),
|
||||||
|
|
||||||
Type::PropertyInstance(_) => KnownClass::Property
|
Type::PropertyInstance(_) => KnownClass::Property
|
||||||
.to_instance(db)
|
.to_instance(db)
|
||||||
|
@ -3174,6 +3191,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::LiteralString
|
| Type::LiteralString
|
||||||
| Type::Tuple(..)
|
| Type::Tuple(..)
|
||||||
| Type::TypeVar(..)
|
| Type::TypeVar(..)
|
||||||
|
| Type::SpecialForm(..)
|
||||||
| Type::KnownInstance(..)
|
| Type::KnownInstance(..)
|
||||||
| Type::PropertyInstance(..)
|
| Type::PropertyInstance(..)
|
||||||
| Type::FunctionLiteral(..) => {
|
| Type::FunctionLiteral(..) => {
|
||||||
|
@ -3455,6 +3473,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::PropertyInstance(_)
|
| Type::PropertyInstance(_)
|
||||||
| Type::BoundSuper(_)
|
| Type::BoundSuper(_)
|
||||||
| Type::KnownInstance(_)
|
| Type::KnownInstance(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::AlwaysTruthy => Truthiness::AlwaysTrue,
|
| Type::AlwaysTruthy => Truthiness::AlwaysTrue,
|
||||||
|
|
||||||
Type::AlwaysFalsy => Truthiness::AlwaysFalse,
|
Type::AlwaysFalsy => Truthiness::AlwaysFalse,
|
||||||
|
@ -4276,7 +4295,7 @@ impl<'db> Type<'db> {
|
||||||
.into(),
|
.into(),
|
||||||
},
|
},
|
||||||
|
|
||||||
Type::KnownInstance(KnownInstanceType::TypedDict) => {
|
Type::SpecialForm(SpecialFormType::TypedDict) => {
|
||||||
Binding::single(
|
Binding::single(
|
||||||
self,
|
self,
|
||||||
Signature::new(
|
Signature::new(
|
||||||
|
@ -4369,10 +4388,11 @@ impl<'db> Type<'db> {
|
||||||
CallableBinding::not_callable(self).into()
|
CallableBinding::not_callable(self).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: some `KnownInstance`s are callable (e.g. TypedDicts)
|
// TODO: some `SpecialForm`s are callable (e.g. TypedDicts)
|
||||||
Type::KnownInstance(_) => CallableBinding::not_callable(self).into(),
|
Type::SpecialForm(_) => CallableBinding::not_callable(self).into(),
|
||||||
|
|
||||||
Type::PropertyInstance(_)
|
Type::PropertyInstance(_)
|
||||||
|
| Type::KnownInstance(_)
|
||||||
| Type::AlwaysFalsy
|
| Type::AlwaysFalsy
|
||||||
| Type::AlwaysTruthy
|
| Type::AlwaysTruthy
|
||||||
| Type::IntLiteral(_)
|
| Type::IntLiteral(_)
|
||||||
|
@ -4861,6 +4881,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::DataclassTransformer(_)
|
| Type::DataclassTransformer(_)
|
||||||
| Type::NominalInstance(_)
|
| Type::NominalInstance(_)
|
||||||
| Type::ProtocolInstance(_)
|
| Type::ProtocolInstance(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::KnownInstance(_)
|
| Type::KnownInstance(_)
|
||||||
| Type::PropertyInstance(_)
|
| Type::PropertyInstance(_)
|
||||||
| Type::ModuleLiteral(_)
|
| Type::ModuleLiteral(_)
|
||||||
|
@ -4942,33 +4963,43 @@ impl<'db> Type<'db> {
|
||||||
|
|
||||||
Type::KnownInstance(known_instance) => match known_instance {
|
Type::KnownInstance(known_instance) => match known_instance {
|
||||||
KnownInstanceType::TypeAliasType(alias) => Ok(alias.value_type(db)),
|
KnownInstanceType::TypeAliasType(alias) => Ok(alias.value_type(db)),
|
||||||
KnownInstanceType::Never | KnownInstanceType::NoReturn => Ok(Type::Never),
|
KnownInstanceType::TypeVar(typevar) => Ok(Type::TypeVar(*typevar)),
|
||||||
KnownInstanceType::LiteralString => Ok(Type::LiteralString),
|
KnownInstanceType::SubscriptedProtocol(_) => Err(InvalidTypeExpressionError {
|
||||||
KnownInstanceType::Unknown => Ok(Type::unknown()),
|
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::Protocol],
|
||||||
KnownInstanceType::AlwaysTruthy => Ok(Type::AlwaysTruthy),
|
fallback_type: Type::unknown(),
|
||||||
KnownInstanceType::AlwaysFalsy => Ok(Type::AlwaysFalsy),
|
}),
|
||||||
|
KnownInstanceType::SubscriptedGeneric(_) => Err(InvalidTypeExpressionError {
|
||||||
|
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::Generic],
|
||||||
|
fallback_type: Type::unknown(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
|
||||||
|
Type::SpecialForm(special_form) => match special_form {
|
||||||
|
SpecialFormType::Never | SpecialFormType::NoReturn => Ok(Type::Never),
|
||||||
|
SpecialFormType::LiteralString => Ok(Type::LiteralString),
|
||||||
|
SpecialFormType::Unknown => Ok(Type::unknown()),
|
||||||
|
SpecialFormType::AlwaysTruthy => Ok(Type::AlwaysTruthy),
|
||||||
|
SpecialFormType::AlwaysFalsy => Ok(Type::AlwaysFalsy),
|
||||||
|
|
||||||
// We treat `typing.Type` exactly the same as `builtins.type`:
|
// We treat `typing.Type` exactly the same as `builtins.type`:
|
||||||
KnownInstanceType::Type => Ok(KnownClass::Type.to_instance(db)),
|
SpecialFormType::Type => Ok(KnownClass::Type.to_instance(db)),
|
||||||
KnownInstanceType::Tuple => Ok(KnownClass::Tuple.to_instance(db)),
|
SpecialFormType::Tuple => Ok(KnownClass::Tuple.to_instance(db)),
|
||||||
|
|
||||||
// Legacy `typing` aliases
|
// Legacy `typing` aliases
|
||||||
KnownInstanceType::List => Ok(KnownClass::List.to_instance(db)),
|
SpecialFormType::List => Ok(KnownClass::List.to_instance(db)),
|
||||||
KnownInstanceType::Dict => Ok(KnownClass::Dict.to_instance(db)),
|
SpecialFormType::Dict => Ok(KnownClass::Dict.to_instance(db)),
|
||||||
KnownInstanceType::Set => Ok(KnownClass::Set.to_instance(db)),
|
SpecialFormType::Set => Ok(KnownClass::Set.to_instance(db)),
|
||||||
KnownInstanceType::FrozenSet => Ok(KnownClass::FrozenSet.to_instance(db)),
|
SpecialFormType::FrozenSet => Ok(KnownClass::FrozenSet.to_instance(db)),
|
||||||
KnownInstanceType::ChainMap => Ok(KnownClass::ChainMap.to_instance(db)),
|
SpecialFormType::ChainMap => Ok(KnownClass::ChainMap.to_instance(db)),
|
||||||
KnownInstanceType::Counter => Ok(KnownClass::Counter.to_instance(db)),
|
SpecialFormType::Counter => Ok(KnownClass::Counter.to_instance(db)),
|
||||||
KnownInstanceType::DefaultDict => Ok(KnownClass::DefaultDict.to_instance(db)),
|
SpecialFormType::DefaultDict => Ok(KnownClass::DefaultDict.to_instance(db)),
|
||||||
KnownInstanceType::Deque => Ok(KnownClass::Deque.to_instance(db)),
|
SpecialFormType::Deque => Ok(KnownClass::Deque.to_instance(db)),
|
||||||
KnownInstanceType::OrderedDict => Ok(KnownClass::OrderedDict.to_instance(db)),
|
SpecialFormType::OrderedDict => Ok(KnownClass::OrderedDict.to_instance(db)),
|
||||||
|
|
||||||
KnownInstanceType::TypeVar(typevar) => Ok(Type::TypeVar(*typevar)),
|
|
||||||
|
|
||||||
// TODO: Use an opt-in rule for a bare `Callable`
|
// TODO: Use an opt-in rule for a bare `Callable`
|
||||||
KnownInstanceType::Callable => Ok(CallableType::unknown(db)),
|
SpecialFormType::Callable => Ok(CallableType::unknown(db)),
|
||||||
|
|
||||||
KnownInstanceType::TypingSelf => {
|
SpecialFormType::TypingSelf => {
|
||||||
let index = semantic_index(db, scope_id.file(db));
|
let index = semantic_index(db, scope_id.file(db));
|
||||||
let Some(class) = nearest_enclosing_class(db, index, scope_id) else {
|
let Some(class) = nearest_enclosing_class(db, index, scope_id) else {
|
||||||
return Err(InvalidTypeExpressionError {
|
return Err(InvalidTypeExpressionError {
|
||||||
|
@ -4991,41 +5022,41 @@ impl<'db> Type<'db> {
|
||||||
TypeVarKind::Legacy,
|
TypeVarKind::Legacy,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
KnownInstanceType::TypeAlias => Ok(todo_type!("Support for `typing.TypeAlias`")),
|
SpecialFormType::TypeAlias => Ok(todo_type!("Support for `typing.TypeAlias`")),
|
||||||
KnownInstanceType::TypedDict => Ok(todo_type!("Support for `typing.TypedDict`")),
|
SpecialFormType::TypedDict => Ok(todo_type!("Support for `typing.TypedDict`")),
|
||||||
|
|
||||||
KnownInstanceType::Protocol(_) => Err(InvalidTypeExpressionError {
|
SpecialFormType::Literal
|
||||||
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::Protocol],
|
| SpecialFormType::Union
|
||||||
fallback_type: Type::unknown(),
|
| SpecialFormType::Intersection => Err(InvalidTypeExpressionError {
|
||||||
}),
|
|
||||||
KnownInstanceType::Generic(_) => Err(InvalidTypeExpressionError {
|
|
||||||
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::Generic],
|
|
||||||
fallback_type: Type::unknown(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
KnownInstanceType::Literal
|
|
||||||
| KnownInstanceType::Union
|
|
||||||
| KnownInstanceType::Intersection => Err(InvalidTypeExpressionError {
|
|
||||||
invalid_expressions: smallvec::smallvec![
|
invalid_expressions: smallvec::smallvec![
|
||||||
InvalidTypeExpression::RequiresArguments(*self)
|
InvalidTypeExpression::RequiresArguments(*self)
|
||||||
],
|
],
|
||||||
fallback_type: Type::unknown(),
|
fallback_type: Type::unknown(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
KnownInstanceType::Optional
|
SpecialFormType::Protocol => Err(InvalidTypeExpressionError {
|
||||||
| KnownInstanceType::Not
|
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::Protocol],
|
||||||
| KnownInstanceType::TypeOf
|
fallback_type: Type::unknown(),
|
||||||
| KnownInstanceType::TypeIs
|
}),
|
||||||
| KnownInstanceType::TypeGuard
|
SpecialFormType::Generic => Err(InvalidTypeExpressionError {
|
||||||
| KnownInstanceType::Unpack
|
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::Generic],
|
||||||
| KnownInstanceType::CallableTypeOf => Err(InvalidTypeExpressionError {
|
fallback_type: Type::unknown(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
SpecialFormType::Optional
|
||||||
|
| SpecialFormType::Not
|
||||||
|
| SpecialFormType::TypeOf
|
||||||
|
| SpecialFormType::TypeIs
|
||||||
|
| SpecialFormType::TypeGuard
|
||||||
|
| SpecialFormType::Unpack
|
||||||
|
| SpecialFormType::CallableTypeOf => Err(InvalidTypeExpressionError {
|
||||||
invalid_expressions: smallvec::smallvec![
|
invalid_expressions: smallvec::smallvec![
|
||||||
InvalidTypeExpression::RequiresOneArgument(*self)
|
InvalidTypeExpression::RequiresOneArgument(*self)
|
||||||
],
|
],
|
||||||
fallback_type: Type::unknown(),
|
fallback_type: Type::unknown(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
KnownInstanceType::Annotated | KnownInstanceType::Concatenate => {
|
SpecialFormType::Annotated | SpecialFormType::Concatenate => {
|
||||||
Err(InvalidTypeExpressionError {
|
Err(InvalidTypeExpressionError {
|
||||||
invalid_expressions: smallvec::smallvec![
|
invalid_expressions: smallvec::smallvec![
|
||||||
InvalidTypeExpression::RequiresTwoArguments(*self)
|
InvalidTypeExpression::RequiresTwoArguments(*self)
|
||||||
|
@ -5034,20 +5065,20 @@ impl<'db> Type<'db> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
KnownInstanceType::ClassVar | KnownInstanceType::Final => {
|
SpecialFormType::ClassVar | SpecialFormType::Final => {
|
||||||
Err(InvalidTypeExpressionError {
|
Err(InvalidTypeExpressionError {
|
||||||
invalid_expressions: smallvec::smallvec![
|
invalid_expressions: smallvec::smallvec![
|
||||||
InvalidTypeExpression::TypeQualifier(*known_instance)
|
InvalidTypeExpression::TypeQualifier(*special_form)
|
||||||
],
|
],
|
||||||
fallback_type: Type::unknown(),
|
fallback_type: Type::unknown(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
KnownInstanceType::ReadOnly
|
SpecialFormType::ReadOnly
|
||||||
| KnownInstanceType::NotRequired
|
| SpecialFormType::NotRequired
|
||||||
| KnownInstanceType::Required => Err(InvalidTypeExpressionError {
|
| SpecialFormType::Required => Err(InvalidTypeExpressionError {
|
||||||
invalid_expressions: smallvec::smallvec![
|
invalid_expressions: smallvec::smallvec![
|
||||||
InvalidTypeExpression::TypeQualifierRequiresOneArgument(*known_instance)
|
InvalidTypeExpression::TypeQualifierRequiresOneArgument(*special_form)
|
||||||
],
|
],
|
||||||
fallback_type: Type::unknown(),
|
fallback_type: Type::unknown(),
|
||||||
}),
|
}),
|
||||||
|
@ -5158,6 +5189,7 @@ impl<'db> Type<'db> {
|
||||||
Type::Never => Type::Never,
|
Type::Never => Type::Never,
|
||||||
Type::NominalInstance(instance) => instance.to_meta_type(db),
|
Type::NominalInstance(instance) => instance.to_meta_type(db),
|
||||||
Type::KnownInstance(known_instance) => known_instance.to_meta_type(db),
|
Type::KnownInstance(known_instance) => known_instance.to_meta_type(db),
|
||||||
|
Type::SpecialForm(special_form) => special_form.to_meta_type(db),
|
||||||
Type::PropertyInstance(_) => KnownClass::Property.to_class_literal(db),
|
Type::PropertyInstance(_) => KnownClass::Property.to_class_literal(db),
|
||||||
Type::Union(union) => union.map(db, |ty| ty.to_meta_type(db)),
|
Type::Union(union) => union.map(db, |ty| ty.to_meta_type(db)),
|
||||||
Type::BooleanLiteral(_) => KnownClass::Bool.to_class_literal(db),
|
Type::BooleanLiteral(_) => KnownClass::Bool.to_class_literal(db),
|
||||||
|
@ -5359,6 +5391,7 @@ impl<'db> Type<'db> {
|
||||||
// some other generic context's specialization is applied to it.
|
// some other generic context's specialization is applied to it.
|
||||||
| Type::ClassLiteral(_)
|
| Type::ClassLiteral(_)
|
||||||
| Type::BoundSuper(_)
|
| Type::BoundSuper(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::KnownInstance(_) => self,
|
| Type::KnownInstance(_) => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5458,6 +5491,7 @@ impl<'db> Type<'db> {
|
||||||
| Type::StringLiteral(_)
|
| Type::StringLiteral(_)
|
||||||
| Type::BytesLiteral(_)
|
| Type::BytesLiteral(_)
|
||||||
| Type::BoundSuper(_)
|
| Type::BoundSuper(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::KnownInstance(_) => {}
|
| Type::KnownInstance(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5472,6 +5506,7 @@ impl<'db> Type<'db> {
|
||||||
match self {
|
match self {
|
||||||
Type::IntLiteral(_) | Type::BooleanLiteral(_) => self.repr(db),
|
Type::IntLiteral(_) | Type::BooleanLiteral(_) => self.repr(db),
|
||||||
Type::StringLiteral(_) | Type::LiteralString => *self,
|
Type::StringLiteral(_) | Type::LiteralString => *self,
|
||||||
|
Type::SpecialForm(special_form) => Type::string_literal(db, special_form.repr()),
|
||||||
Type::KnownInstance(known_instance) => Type::StringLiteral(StringLiteralType::new(
|
Type::KnownInstance(known_instance) => Type::StringLiteral(StringLiteralType::new(
|
||||||
db,
|
db,
|
||||||
known_instance.repr(db).to_string().into_boxed_str(),
|
known_instance.repr(db).to_string().into_boxed_str(),
|
||||||
|
@ -5493,6 +5528,7 @@ impl<'db> Type<'db> {
|
||||||
Type::string_literal(db, &format!("'{}'", literal.value(db).escape_default()))
|
Type::string_literal(db, &format!("'{}'", literal.value(db).escape_default()))
|
||||||
}
|
}
|
||||||
Type::LiteralString => Type::LiteralString,
|
Type::LiteralString => Type::LiteralString,
|
||||||
|
Type::SpecialForm(special_form) => Type::string_literal(db, special_form.repr()),
|
||||||
Type::KnownInstance(known_instance) => Type::StringLiteral(StringLiteralType::new(
|
Type::KnownInstance(known_instance) => Type::StringLiteral(StringLiteralType::new(
|
||||||
db,
|
db,
|
||||||
known_instance.repr(db).to_string().into_boxed_str(),
|
known_instance.repr(db).to_string().into_boxed_str(),
|
||||||
|
@ -5568,6 +5604,7 @@ impl<'db> Type<'db> {
|
||||||
| Self::Never
|
| Self::Never
|
||||||
| Self::Callable(_)
|
| Self::Callable(_)
|
||||||
| Self::AlwaysTruthy
|
| Self::AlwaysTruthy
|
||||||
|
| Self::SpecialForm(_)
|
||||||
| Self::AlwaysFalsy => None,
|
| Self::AlwaysFalsy => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5684,6 +5721,112 @@ impl<'db> TypeMapping<'_, 'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Singleton types that are heavily special-cased by ty. Despite its name,
|
||||||
|
/// quite a different type to [`NominalInstanceType`].
|
||||||
|
///
|
||||||
|
/// In many ways, this enum behaves similarly to [`SpecialFormType`].
|
||||||
|
/// Unlike instances of that variant, however, `Type::KnownInstance`s do not exist
|
||||||
|
/// at a location that can be known prior to any analysis by ty, and each variant
|
||||||
|
/// of `KnownInstanceType` can have multiple instances (as, unlike `SpecialFormType`,
|
||||||
|
/// `KnownInstanceType` variants can hold associated data). Instances of this type
|
||||||
|
/// are generally created by operations at runtime in some way, such as a type alias
|
||||||
|
/// statement, a typevar definition, or an instance of `Generic[T]` in a class's
|
||||||
|
/// bases list.
|
||||||
|
///
|
||||||
|
/// # Ordering
|
||||||
|
///
|
||||||
|
/// Ordering between variants is stable and should be the same between runs.
|
||||||
|
/// Ordering within variants is based on the wrapped data's salsa-assigned id and not on its values.
|
||||||
|
/// The id may change between runs, or when e.g. a `TypeVarInstance` was garbage-collected and recreated.
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, salsa::Update, Ord, PartialOrd)]
|
||||||
|
pub enum KnownInstanceType<'db> {
|
||||||
|
/// The type of `Protocol[T]`, `Protocol[U, S]`, etc -- usually only found in a class's bases list.
|
||||||
|
///
|
||||||
|
/// Note that unsubscripted `Protocol` is represented by [`SpecialFormType::Protocol`], not this type.
|
||||||
|
SubscriptedProtocol(GenericContext<'db>),
|
||||||
|
|
||||||
|
/// The type of `Generic[T]`, `Generic[U, S]`, etc -- usually only found in a class's bases list.
|
||||||
|
///
|
||||||
|
/// Note that unsubscripted `Generic` is represented by [`SpecialFormType::Generic`], not this type.
|
||||||
|
SubscriptedGeneric(GenericContext<'db>),
|
||||||
|
|
||||||
|
/// A single instance of `typing.TypeVar`
|
||||||
|
TypeVar(TypeVarInstance<'db>),
|
||||||
|
|
||||||
|
/// A single instance of `typing.TypeAliasType` (PEP 695 type alias)
|
||||||
|
TypeAliasType(TypeAliasType<'db>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'db> KnownInstanceType<'db> {
|
||||||
|
fn normalized(self, db: &'db dyn Db) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::SubscriptedProtocol(context) => Self::SubscriptedProtocol(context.normalized(db)),
|
||||||
|
Self::SubscriptedGeneric(context) => Self::SubscriptedGeneric(context.normalized(db)),
|
||||||
|
Self::TypeVar(typevar) => Self::TypeVar(typevar.normalized(db)),
|
||||||
|
Self::TypeAliasType(type_alias) => Self::TypeAliasType(type_alias.normalized(db)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn class(self) -> KnownClass {
|
||||||
|
match self {
|
||||||
|
Self::SubscriptedProtocol(_) | Self::SubscriptedGeneric(_) => KnownClass::SpecialForm,
|
||||||
|
Self::TypeVar(_) => KnownClass::TypeVar,
|
||||||
|
Self::TypeAliasType(_) => KnownClass::TypeAliasType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_meta_type(self, db: &'db dyn Db) -> Type<'db> {
|
||||||
|
self.class().to_class_literal(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the instance type which this type is a subtype of.
|
||||||
|
///
|
||||||
|
/// For example, an alias created using the `type` statement is an instance of
|
||||||
|
/// `typing.TypeAliasType`, so `KnownInstanceType::TypeAliasType(_).instance_fallback(db)`
|
||||||
|
/// returns `Type::NominalInstance(NominalInstanceType { class: <typing.TypeAliasType> })`.
|
||||||
|
fn instance_fallback(self, db: &dyn Db) -> Type {
|
||||||
|
self.class().to_instance(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if this symbol is an instance of `class`.
|
||||||
|
fn is_instance_of(self, db: &dyn Db, class: ClassType) -> bool {
|
||||||
|
self.class().is_subclass_of(db, class)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the repr of the symbol at runtime
|
||||||
|
fn repr(self, db: &'db dyn Db) -> impl std::fmt::Display + 'db {
|
||||||
|
struct KnownInstanceRepr<'db> {
|
||||||
|
known_instance: KnownInstanceType<'db>,
|
||||||
|
db: &'db dyn Db,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for KnownInstanceRepr<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self.known_instance {
|
||||||
|
KnownInstanceType::SubscriptedProtocol(generic_context) => {
|
||||||
|
f.write_str("typing.Protocol")?;
|
||||||
|
generic_context.display(self.db).fmt(f)
|
||||||
|
}
|
||||||
|
KnownInstanceType::SubscriptedGeneric(generic_context) => {
|
||||||
|
f.write_str("typing.Generic")?;
|
||||||
|
generic_context.display(self.db).fmt(f)
|
||||||
|
}
|
||||||
|
KnownInstanceType::TypeAliasType(_) => f.write_str("typing.TypeAliasType"),
|
||||||
|
// This is a legacy `TypeVar` _outside_ of any generic class or function, so we render
|
||||||
|
// it as an instance of `typing.TypeVar`. Inside of a generic class or function, we'll
|
||||||
|
// have a `Type::TypeVar(_)`, which is rendered as the typevar's name.
|
||||||
|
KnownInstanceType::TypeVar(_) => f.write_str("typing.TypeVar"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KnownInstanceRepr {
|
||||||
|
known_instance: self,
|
||||||
|
db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
pub enum DynamicType {
|
pub enum DynamicType {
|
||||||
// An explicitly annotated `typing.Any`
|
// An explicitly annotated `typing.Any`
|
||||||
|
@ -5841,10 +5984,10 @@ enum InvalidTypeExpression<'db> {
|
||||||
Generic,
|
Generic,
|
||||||
/// Type qualifiers are always invalid in *type expressions*,
|
/// Type qualifiers are always invalid in *type expressions*,
|
||||||
/// but these ones are okay with 0 arguments in *annotation expressions*
|
/// but these ones are okay with 0 arguments in *annotation expressions*
|
||||||
TypeQualifier(KnownInstanceType<'db>),
|
TypeQualifier(SpecialFormType),
|
||||||
/// Type qualifiers that are invalid in type expressions,
|
/// Type qualifiers that are invalid in type expressions,
|
||||||
/// and which would require exactly one argument even if they appeared in an annotation expression
|
/// and which would require exactly one argument even if they appeared in an annotation expression
|
||||||
TypeQualifierRequiresOneArgument(KnownInstanceType<'db>),
|
TypeQualifierRequiresOneArgument(SpecialFormType),
|
||||||
/// Some types are always invalid in type expressions
|
/// Some types are always invalid in type expressions
|
||||||
InvalidType(Type<'db>, ScopeId<'db>),
|
InvalidType(Type<'db>, ScopeId<'db>),
|
||||||
}
|
}
|
||||||
|
@ -5882,13 +6025,13 @@ impl<'db> InvalidTypeExpression<'db> {
|
||||||
}
|
}
|
||||||
InvalidTypeExpression::TypeQualifier(qualifier) => write!(
|
InvalidTypeExpression::TypeQualifier(qualifier) => write!(
|
||||||
f,
|
f,
|
||||||
"Type qualifier `{q}` is not allowed in type expressions (only in annotation expressions)",
|
"Type qualifier `{qualifier}` is not allowed in type expressions \
|
||||||
q = qualifier.repr(self.db)
|
(only in annotation expressions)",
|
||||||
),
|
),
|
||||||
InvalidTypeExpression::TypeQualifierRequiresOneArgument(qualifier) => write!(
|
InvalidTypeExpression::TypeQualifierRequiresOneArgument(qualifier) => write!(
|
||||||
f,
|
f,
|
||||||
"Type qualifier `{q}` is not allowed in type expressions (only in annotation expressions, and only with exactly one argument)",
|
"Type qualifier `{qualifier}` is not allowed in type expressions \
|
||||||
q = qualifier.repr(self.db)
|
(only in annotation expressions, and only with exactly one argument)",
|
||||||
),
|
),
|
||||||
InvalidTypeExpression::InvalidType(ty, _) => write!(
|
InvalidTypeExpression::InvalidType(ty, _) => write!(
|
||||||
f,
|
f,
|
||||||
|
@ -8827,8 +8970,8 @@ impl<'db> SuperOwnerKind<'db> {
|
||||||
Type::BytesLiteral(_) => {
|
Type::BytesLiteral(_) => {
|
||||||
SuperOwnerKind::try_from_type(db, KnownClass::Bytes.to_instance(db))
|
SuperOwnerKind::try_from_type(db, KnownClass::Bytes.to_instance(db))
|
||||||
}
|
}
|
||||||
Type::KnownInstance(known_instance) => {
|
Type::SpecialForm(special_form) => {
|
||||||
SuperOwnerKind::try_from_type(db, known_instance.instance_fallback(db))
|
SuperOwnerKind::try_from_type(db, special_form.instance_fallback(db))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::types::signatures::{Parameter, ParameterForm};
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
BoundMethodType, DataclassParams, DataclassTransformerParams, FunctionDecorators, FunctionType,
|
BoundMethodType, DataclassParams, DataclassTransformerParams, FunctionDecorators, FunctionType,
|
||||||
KnownClass, KnownFunction, KnownInstanceType, MethodWrapperKind, PropertyInstanceType,
|
KnownClass, KnownFunction, KnownInstanceType, MethodWrapperKind, PropertyInstanceType,
|
||||||
TupleType, TypeMapping, UnionType, WrapperDescriptorKind, todo_type,
|
SpecialFormType, TupleType, TypeMapping, UnionType, WrapperDescriptorKind, todo_type,
|
||||||
};
|
};
|
||||||
use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic};
|
use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic};
|
||||||
use ruff_python_ast as ast;
|
use ruff_python_ast as ast;
|
||||||
|
@ -933,7 +933,7 @@ impl<'db> Bindings<'db> {
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
|
||||||
Type::KnownInstance(KnownInstanceType::TypedDict) => {
|
Type::SpecialForm(SpecialFormType::TypedDict) => {
|
||||||
overload.set_return_type(todo_type!("TypedDict"));
|
overload.set_return_type(todo_type!("TypedDict"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ use std::sync::{LazyLock, Mutex};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
IntersectionBuilder, KnownFunction, MemberLookupPolicy, Mro, MroError, MroIterator,
|
IntersectionBuilder, KnownFunction, MemberLookupPolicy, Mro, MroError, MroIterator,
|
||||||
SubclassOfType, Truthiness, Type, TypeQualifiers, class_base::ClassBase, infer_expression_type,
|
SpecialFormType, SubclassOfType, Truthiness, Type, TypeQualifiers, class_base::ClassBase,
|
||||||
infer_unpack_types,
|
infer_expression_type, infer_unpack_types,
|
||||||
};
|
};
|
||||||
use crate::semantic_index::DeclarationWithConstraint;
|
use crate::semantic_index::DeclarationWithConstraint;
|
||||||
use crate::semantic_index::definition::Definition;
|
use crate::semantic_index::definition::Definition;
|
||||||
|
@ -729,9 +729,9 @@ impl<'db> ClassLiteral<'db> {
|
||||||
pub(crate) fn legacy_generic_context(self, db: &'db dyn Db) -> Option<GenericContext<'db>> {
|
pub(crate) fn legacy_generic_context(self, db: &'db dyn Db) -> Option<GenericContext<'db>> {
|
||||||
self.explicit_bases(db).iter().find_map(|base| match base {
|
self.explicit_bases(db).iter().find_map(|base| match base {
|
||||||
Type::KnownInstance(
|
Type::KnownInstance(
|
||||||
KnownInstanceType::Generic(generic_context)
|
KnownInstanceType::SubscriptedGeneric(generic_context)
|
||||||
| KnownInstanceType::Protocol(generic_context),
|
| KnownInstanceType::SubscriptedProtocol(generic_context),
|
||||||
) => *generic_context,
|
) => Some(*generic_context),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -879,11 +879,13 @@ impl<'db> ClassLiteral<'db> {
|
||||||
// - OR be the last-but-one base (with the final base being `Generic[]` or `object`)
|
// - OR be the last-but-one base (with the final base being `Generic[]` or `object`)
|
||||||
// - OR be the last-but-two base (with the penultimate base being `Generic[]`
|
// - OR be the last-but-two base (with the penultimate base being `Generic[]`
|
||||||
// and the final base being `object`)
|
// and the final base being `object`)
|
||||||
self.explicit_bases(db)
|
self.explicit_bases(db).iter().rev().take(3).any(|base| {
|
||||||
.iter()
|
matches!(
|
||||||
.rev()
|
base,
|
||||||
.take(3)
|
Type::SpecialForm(SpecialFormType::Protocol)
|
||||||
.any(|base| matches!(base, Type::KnownInstance(KnownInstanceType::Protocol(_))))
|
| Type::KnownInstance(KnownInstanceType::SubscriptedProtocol(_))
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::Db;
|
use crate::Db;
|
||||||
use crate::types::generics::Specialization;
|
use crate::types::generics::Specialization;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ClassType, DynamicType, KnownClass, KnownInstanceType, MroError, MroIterator, Type,
|
ClassType, DynamicType, KnownClass, KnownInstanceType, MroError, MroIterator, SpecialFormType,
|
||||||
TypeMapping, todo_type,
|
Type, TypeMapping, todo_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Enumeration of the possible kinds of types we allow in class bases.
|
/// Enumeration of the possible kinds of types we allow in class bases.
|
||||||
|
@ -147,74 +147,82 @@ impl<'db> ClassBase<'db> {
|
||||||
| Type::ProtocolInstance(_)
|
| Type::ProtocolInstance(_)
|
||||||
| Type::AlwaysFalsy
|
| Type::AlwaysFalsy
|
||||||
| Type::AlwaysTruthy => None,
|
| Type::AlwaysTruthy => None,
|
||||||
|
|
||||||
Type::KnownInstance(known_instance) => match known_instance {
|
Type::KnownInstance(known_instance) => match known_instance {
|
||||||
KnownInstanceType::TypeVar(_)
|
KnownInstanceType::SubscriptedGeneric(_) => Some(Self::Generic),
|
||||||
| KnownInstanceType::TypeAliasType(_)
|
KnownInstanceType::SubscriptedProtocol(_) => Some(Self::Protocol),
|
||||||
| KnownInstanceType::Annotated
|
KnownInstanceType::TypeAliasType(_) | KnownInstanceType::TypeVar(_) => None,
|
||||||
| KnownInstanceType::Literal
|
},
|
||||||
| KnownInstanceType::LiteralString
|
|
||||||
| KnownInstanceType::Union
|
Type::SpecialForm(special_form) => match special_form {
|
||||||
| KnownInstanceType::NoReturn
|
SpecialFormType::Annotated
|
||||||
| KnownInstanceType::Never
|
| SpecialFormType::Literal
|
||||||
| KnownInstanceType::Final
|
| SpecialFormType::LiteralString
|
||||||
| KnownInstanceType::NotRequired
|
| SpecialFormType::Union
|
||||||
| KnownInstanceType::TypeGuard
|
| SpecialFormType::NoReturn
|
||||||
| KnownInstanceType::TypeIs
|
| SpecialFormType::Never
|
||||||
| KnownInstanceType::TypingSelf
|
| SpecialFormType::Final
|
||||||
| KnownInstanceType::Unpack
|
| SpecialFormType::NotRequired
|
||||||
| KnownInstanceType::ClassVar
|
| SpecialFormType::TypeGuard
|
||||||
| KnownInstanceType::Concatenate
|
| SpecialFormType::TypeIs
|
||||||
| KnownInstanceType::Required
|
| SpecialFormType::TypingSelf
|
||||||
| KnownInstanceType::TypeAlias
|
| SpecialFormType::Unpack
|
||||||
| KnownInstanceType::ReadOnly
|
| SpecialFormType::ClassVar
|
||||||
| KnownInstanceType::Optional
|
| SpecialFormType::Concatenate
|
||||||
| KnownInstanceType::Not
|
| SpecialFormType::Required
|
||||||
| KnownInstanceType::Intersection
|
| SpecialFormType::TypeAlias
|
||||||
| KnownInstanceType::TypeOf
|
| SpecialFormType::ReadOnly
|
||||||
| KnownInstanceType::CallableTypeOf
|
| SpecialFormType::Optional
|
||||||
| KnownInstanceType::AlwaysTruthy
|
| SpecialFormType::Not
|
||||||
| KnownInstanceType::AlwaysFalsy => None,
|
| SpecialFormType::Intersection
|
||||||
KnownInstanceType::Unknown => Some(Self::unknown()),
|
| SpecialFormType::TypeOf
|
||||||
|
| SpecialFormType::CallableTypeOf
|
||||||
|
| SpecialFormType::AlwaysTruthy
|
||||||
|
| SpecialFormType::AlwaysFalsy => None,
|
||||||
|
|
||||||
|
SpecialFormType::Unknown => Some(Self::unknown()),
|
||||||
|
|
||||||
|
SpecialFormType::Protocol => Some(Self::Protocol),
|
||||||
|
SpecialFormType::Generic => Some(Self::Generic),
|
||||||
|
|
||||||
// TODO: Classes inheriting from `typing.Type` et al. also have `Generic` in their MRO
|
// TODO: Classes inheriting from `typing.Type` et al. also have `Generic` in their MRO
|
||||||
KnownInstanceType::Dict => {
|
SpecialFormType::Dict => {
|
||||||
Self::try_from_type(db, KnownClass::Dict.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Dict.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::List => {
|
SpecialFormType::List => {
|
||||||
Self::try_from_type(db, KnownClass::List.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::List.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Type => {
|
SpecialFormType::Type => {
|
||||||
Self::try_from_type(db, KnownClass::Type.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Type.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Tuple => {
|
SpecialFormType::Tuple => {
|
||||||
Self::try_from_type(db, KnownClass::Tuple.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Tuple.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Set => {
|
SpecialFormType::Set => {
|
||||||
Self::try_from_type(db, KnownClass::Set.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Set.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::FrozenSet => {
|
SpecialFormType::FrozenSet => {
|
||||||
Self::try_from_type(db, KnownClass::FrozenSet.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::FrozenSet.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::ChainMap => {
|
SpecialFormType::ChainMap => {
|
||||||
Self::try_from_type(db, KnownClass::ChainMap.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::ChainMap.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Counter => {
|
SpecialFormType::Counter => {
|
||||||
Self::try_from_type(db, KnownClass::Counter.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Counter.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::DefaultDict => {
|
SpecialFormType::DefaultDict => {
|
||||||
Self::try_from_type(db, KnownClass::DefaultDict.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::DefaultDict.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Deque => {
|
SpecialFormType::Deque => {
|
||||||
Self::try_from_type(db, KnownClass::Deque.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Deque.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::OrderedDict => {
|
SpecialFormType::OrderedDict => {
|
||||||
Self::try_from_type(db, KnownClass::OrderedDict.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::OrderedDict.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::TypedDict => Self::try_from_type(db, todo_type!("TypedDict")),
|
SpecialFormType::TypedDict => Self::try_from_type(db, todo_type!("TypedDict")),
|
||||||
KnownInstanceType::Callable => {
|
SpecialFormType::Callable => {
|
||||||
Self::try_from_type(db, todo_type!("Support for Callable as a base class"))
|
Self::try_from_type(db, todo_type!("Support for Callable as a base class"))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Protocol(_) => Some(ClassBase::Protocol),
|
|
||||||
KnownInstanceType::Generic(_) => Some(ClassBase::Generic),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,8 +296,8 @@ impl<'db> From<ClassBase<'db>> for Type<'db> {
|
||||||
match value {
|
match value {
|
||||||
ClassBase::Dynamic(dynamic) => Type::Dynamic(dynamic),
|
ClassBase::Dynamic(dynamic) => Type::Dynamic(dynamic),
|
||||||
ClassBase::Class(class) => class.into(),
|
ClassBase::Class(class) => class.into(),
|
||||||
ClassBase::Protocol => Type::KnownInstance(KnownInstanceType::Protocol(None)),
|
ClassBase::Protocol => Type::SpecialForm(SpecialFormType::Protocol),
|
||||||
ClassBase::Generic => Type::KnownInstance(KnownInstanceType::Generic(None)),
|
ClassBase::Generic => Type::SpecialForm(SpecialFormType::Generic),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ use super::{
|
||||||
CallArgumentTypes, CallDunderError, ClassBase, ClassLiteral, KnownClass,
|
CallArgumentTypes, CallDunderError, ClassBase, ClassLiteral, KnownClass,
|
||||||
add_inferred_python_version_hint_to_diagnostic,
|
add_inferred_python_version_hint_to_diagnostic,
|
||||||
};
|
};
|
||||||
use crate::db::Db;
|
|
||||||
use crate::declare_lint;
|
use crate::declare_lint;
|
||||||
use crate::lint::{Level, LintRegistryBuilder, LintStatus};
|
use crate::lint::{Level, LintRegistryBuilder, LintStatus};
|
||||||
use crate::suppression::FileSuppressionId;
|
use crate::suppression::FileSuppressionId;
|
||||||
|
@ -15,7 +14,7 @@ use crate::types::string_annotation::{
|
||||||
IMPLICIT_CONCATENATED_STRING_TYPE_ANNOTATION, INVALID_SYNTAX_IN_FORWARD_ANNOTATION,
|
IMPLICIT_CONCATENATED_STRING_TYPE_ANNOTATION, INVALID_SYNTAX_IN_FORWARD_ANNOTATION,
|
||||||
RAW_STRING_TYPE_ANNOTATION,
|
RAW_STRING_TYPE_ANNOTATION,
|
||||||
};
|
};
|
||||||
use crate::types::{KnownFunction, KnownInstanceType, Type, protocol_class::ProtocolClassLiteral};
|
use crate::types::{KnownFunction, SpecialFormType, Type, protocol_class::ProtocolClassLiteral};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic};
|
use ruff_db::diagnostic::{Annotation, Diagnostic, Severity, SubDiagnostic};
|
||||||
use ruff_python_ast::{self as ast, AnyNodeRef};
|
use ruff_python_ast::{self as ast, AnyNodeRef};
|
||||||
|
@ -1823,7 +1822,6 @@ pub(crate) fn report_base_with_incompatible_slots(context: &InferContext, node:
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn report_invalid_arguments_to_annotated(
|
pub(crate) fn report_invalid_arguments_to_annotated(
|
||||||
db: &dyn Db,
|
|
||||||
context: &InferContext,
|
context: &InferContext,
|
||||||
subscript: &ast::ExprSubscript,
|
subscript: &ast::ExprSubscript,
|
||||||
) {
|
) {
|
||||||
|
@ -1833,7 +1831,7 @@ pub(crate) fn report_invalid_arguments_to_annotated(
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Special form `{}` expected at least 2 arguments \
|
"Special form `{}` expected at least 2 arguments \
|
||||||
(one type and at least one metadata element)",
|
(one type and at least one metadata element)",
|
||||||
KnownInstanceType::Annotated.repr(db)
|
SpecialFormType::Annotated
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1873,7 +1871,6 @@ pub(crate) fn report_bad_argument_to_get_protocol_members(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn report_invalid_arguments_to_callable(
|
pub(crate) fn report_invalid_arguments_to_callable(
|
||||||
db: &dyn Db,
|
|
||||||
context: &InferContext,
|
context: &InferContext,
|
||||||
subscript: &ast::ExprSubscript,
|
subscript: &ast::ExprSubscript,
|
||||||
) {
|
) {
|
||||||
|
@ -1882,7 +1879,7 @@ pub(crate) fn report_invalid_arguments_to_callable(
|
||||||
};
|
};
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Special form `{}` expected exactly two arguments (parameter types and return type)",
|
"Special form `{}` expected exactly two arguments (parameter types and return type)",
|
||||||
KnownInstanceType::Callable.repr(db)
|
SpecialFormType::Callable
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,7 @@ impl Display for DisplayRepresentation<'_> {
|
||||||
SubclassOfInner::Class(class) => write!(f, "type[{}]", class.name(self.db)),
|
SubclassOfInner::Class(class) => write!(f, "type[{}]", class.name(self.db)),
|
||||||
SubclassOfInner::Dynamic(dynamic) => write!(f, "type[{dynamic}]"),
|
SubclassOfInner::Dynamic(dynamic) => write!(f, "type[{dynamic}]"),
|
||||||
},
|
},
|
||||||
|
Type::SpecialForm(special_form) => special_form.fmt(f),
|
||||||
Type::KnownInstance(known_instance) => known_instance.repr(self.db).fmt(f),
|
Type::KnownInstance(known_instance) => known_instance.repr(self.db).fmt(f),
|
||||||
Type::FunctionLiteral(function) => {
|
Type::FunctionLiteral(function) => {
|
||||||
let signature = function.signature(self.db);
|
let signature = function.signature(self.db);
|
||||||
|
|
|
@ -89,7 +89,7 @@ use crate::types::{
|
||||||
BareTypeAliasType, CallDunderError, CallableType, ClassLiteral, ClassType, DataclassParams,
|
BareTypeAliasType, CallDunderError, CallableType, ClassLiteral, ClassType, DataclassParams,
|
||||||
DynamicType, FunctionDecorators, FunctionType, GenericAlias, IntersectionBuilder,
|
DynamicType, FunctionDecorators, FunctionType, GenericAlias, IntersectionBuilder,
|
||||||
IntersectionType, KnownClass, KnownFunction, KnownInstanceType, MemberLookupPolicy,
|
IntersectionType, KnownClass, KnownFunction, KnownInstanceType, MemberLookupPolicy,
|
||||||
MetaclassCandidate, PEP695TypeAliasType, Parameter, ParameterForm, Parameters,
|
MetaclassCandidate, PEP695TypeAliasType, Parameter, ParameterForm, Parameters, SpecialFormType,
|
||||||
StringLiteralType, SubclassOfType, Symbol, SymbolAndQualifiers, Truthiness, TupleType, Type,
|
StringLiteralType, SubclassOfType, Symbol, SymbolAndQualifiers, Truthiness, TupleType, Type,
|
||||||
TypeAliasType, TypeAndQualifiers, TypeArrayDisplay, TypeQualifiers, TypeVarBoundOrConstraints,
|
TypeAliasType, TypeAndQualifiers, TypeArrayDisplay, TypeQualifiers, TypeVarBoundOrConstraints,
|
||||||
TypeVarInstance, TypeVarKind, TypeVarVariance, UnionBuilder, UnionType, binding_type,
|
TypeVarInstance, TypeVarKind, TypeVarVariance, UnionBuilder, UnionType, binding_type,
|
||||||
|
@ -850,7 +850,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
// - If the class is a protocol class: check for inheritance from a non-protocol class
|
// - If the class is a protocol class: check for inheritance from a non-protocol class
|
||||||
for (i, base_class) in class.explicit_bases(self.db()).iter().enumerate() {
|
for (i, base_class) in class.explicit_bases(self.db()).iter().enumerate() {
|
||||||
let base_class = match base_class {
|
let base_class = match base_class {
|
||||||
Type::KnownInstance(KnownInstanceType::Generic(None)) => {
|
Type::SpecialForm(SpecialFormType::Generic) => {
|
||||||
if let Some(builder) = self
|
if let Some(builder) = self
|
||||||
.context
|
.context
|
||||||
.report_lint(&INVALID_BASE, &class_node.bases()[i])
|
.report_lint(&INVALID_BASE, &class_node.bases()[i])
|
||||||
|
@ -864,7 +864,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
// Note that unlike several of the other errors caught in this function,
|
// Note that unlike several of the other errors caught in this function,
|
||||||
// this does not lead to the class creation failing at runtime,
|
// this does not lead to the class creation failing at runtime,
|
||||||
// but it is semantically invalid.
|
// but it is semantically invalid.
|
||||||
Type::KnownInstance(KnownInstanceType::Protocol(Some(_))) => {
|
Type::KnownInstance(KnownInstanceType::SubscriptedProtocol(_)) => {
|
||||||
if class_node.type_params.is_none() {
|
if class_node.type_params.is_none() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -3084,6 +3084,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
| Type::BytesLiteral(..)
|
| Type::BytesLiteral(..)
|
||||||
| Type::LiteralString
|
| Type::LiteralString
|
||||||
| Type::Tuple(..)
|
| Type::Tuple(..)
|
||||||
|
| Type::SpecialForm(..)
|
||||||
| Type::KnownInstance(..)
|
| Type::KnownInstance(..)
|
||||||
| Type::PropertyInstance(..)
|
| Type::PropertyInstance(..)
|
||||||
| Type::FunctionLiteral(..)
|
| Type::FunctionLiteral(..)
|
||||||
|
@ -3544,10 +3545,10 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(known_instance) = target.as_name_expr().and_then(|name| {
|
if let Some(special_form) = target.as_name_expr().and_then(|name| {
|
||||||
KnownInstanceType::try_from_file_and_name(self.db(), self.file(), &name.id)
|
SpecialFormType::try_from_file_and_name(self.db(), self.file(), &name.id)
|
||||||
}) {
|
}) {
|
||||||
target_ty = Type::KnownInstance(known_instance);
|
target_ty = Type::SpecialForm(special_form);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.store_expression_type(target, target_ty);
|
self.store_expression_type(target, target_ty);
|
||||||
|
@ -3631,12 +3632,12 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
if let Type::NominalInstance(instance) = declared_ty.inner_type() {
|
if let Type::NominalInstance(instance) = declared_ty.inner_type() {
|
||||||
if instance.class.is_known(self.db(), KnownClass::SpecialForm) {
|
if instance.class.is_known(self.db(), KnownClass::SpecialForm) {
|
||||||
if let Some(name_expr) = target.as_name_expr() {
|
if let Some(name_expr) = target.as_name_expr() {
|
||||||
if let Some(known_instance) = KnownInstanceType::try_from_file_and_name(
|
if let Some(special_form) = SpecialFormType::try_from_file_and_name(
|
||||||
self.db(),
|
self.db(),
|
||||||
self.file(),
|
self.file(),
|
||||||
&name_expr.id,
|
&name_expr.id,
|
||||||
) {
|
) {
|
||||||
declared_ty.inner = Type::KnownInstance(known_instance);
|
declared_ty.inner = Type::SpecialForm(special_form);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5958,6 +5959,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
| Type::SubclassOf(_)
|
| Type::SubclassOf(_)
|
||||||
| Type::NominalInstance(_)
|
| Type::NominalInstance(_)
|
||||||
| Type::ProtocolInstance(_)
|
| Type::ProtocolInstance(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::KnownInstance(_)
|
| Type::KnownInstance(_)
|
||||||
| Type::PropertyInstance(_)
|
| Type::PropertyInstance(_)
|
||||||
| Type::Union(_)
|
| Type::Union(_)
|
||||||
|
@ -6287,6 +6289,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
| Type::SubclassOf(_)
|
| Type::SubclassOf(_)
|
||||||
| Type::NominalInstance(_)
|
| Type::NominalInstance(_)
|
||||||
| Type::ProtocolInstance(_)
|
| Type::ProtocolInstance(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::KnownInstance(_)
|
| Type::KnownInstance(_)
|
||||||
| Type::PropertyInstance(_)
|
| Type::PropertyInstance(_)
|
||||||
| Type::Intersection(_)
|
| Type::Intersection(_)
|
||||||
|
@ -6312,6 +6315,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
| Type::SubclassOf(_)
|
| Type::SubclassOf(_)
|
||||||
| Type::NominalInstance(_)
|
| Type::NominalInstance(_)
|
||||||
| Type::ProtocolInstance(_)
|
| Type::ProtocolInstance(_)
|
||||||
|
| Type::SpecialForm(_)
|
||||||
| Type::KnownInstance(_)
|
| Type::KnownInstance(_)
|
||||||
| Type::PropertyInstance(_)
|
| Type::PropertyInstance(_)
|
||||||
| Type::Intersection(_)
|
| Type::Intersection(_)
|
||||||
|
@ -7432,48 +7436,49 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
value_ty,
|
value_ty,
|
||||||
Type::IntLiteral(i64::from(bool)),
|
Type::IntLiteral(i64::from(bool)),
|
||||||
),
|
),
|
||||||
(Type::KnownInstance(KnownInstanceType::Protocol(None)), Type::Tuple(typevars), _) => {
|
(Type::SpecialForm(SpecialFormType::Protocol), Type::Tuple(typevars), _) => self
|
||||||
self.legacy_generic_class_context(
|
.legacy_generic_class_context(
|
||||||
value_node,
|
value_node,
|
||||||
typevars.elements(self.db()),
|
typevars.elements(self.db()),
|
||||||
LegacyGenericBase::Protocol,
|
LegacyGenericBase::Protocol,
|
||||||
)
|
)
|
||||||
.map(|context| Type::KnownInstance(KnownInstanceType::Protocol(Some(context))))
|
.map(|context| Type::KnownInstance(KnownInstanceType::SubscriptedProtocol(context)))
|
||||||
.unwrap_or_else(Type::unknown)
|
.unwrap_or_else(Type::unknown),
|
||||||
}
|
(Type::SpecialForm(SpecialFormType::Protocol), typevar, _) => self
|
||||||
(Type::KnownInstance(KnownInstanceType::Protocol(None)), typevar, _) => self
|
|
||||||
.legacy_generic_class_context(
|
.legacy_generic_class_context(
|
||||||
value_node,
|
value_node,
|
||||||
std::slice::from_ref(&typevar),
|
std::slice::from_ref(&typevar),
|
||||||
LegacyGenericBase::Protocol,
|
LegacyGenericBase::Protocol,
|
||||||
)
|
)
|
||||||
.map(|context| Type::KnownInstance(KnownInstanceType::Protocol(Some(context))))
|
.map(|context| Type::KnownInstance(KnownInstanceType::SubscriptedProtocol(context)))
|
||||||
.unwrap_or_else(Type::unknown),
|
.unwrap_or_else(Type::unknown),
|
||||||
(Type::KnownInstance(KnownInstanceType::Protocol(Some(_))), _, _) => {
|
(Type::KnownInstance(KnownInstanceType::SubscriptedProtocol(_)), _, _) => {
|
||||||
// TODO: emit a diagnostic
|
// TODO: emit a diagnostic
|
||||||
todo_type!("doubly-specialized typing.Protocol")
|
todo_type!("doubly-specialized typing.Protocol")
|
||||||
}
|
}
|
||||||
(Type::KnownInstance(KnownInstanceType::Generic(None)), Type::Tuple(typevars), _) => {
|
(Type::SpecialForm(SpecialFormType::Generic), Type::Tuple(typevars), _) => self
|
||||||
self.legacy_generic_class_context(
|
.legacy_generic_class_context(
|
||||||
value_node,
|
value_node,
|
||||||
typevars.elements(self.db()),
|
typevars.elements(self.db()),
|
||||||
LegacyGenericBase::Generic,
|
LegacyGenericBase::Generic,
|
||||||
)
|
)
|
||||||
.map(|context| Type::KnownInstance(KnownInstanceType::Generic(Some(context))))
|
.map(|context| Type::KnownInstance(KnownInstanceType::SubscriptedGeneric(context)))
|
||||||
.unwrap_or_else(Type::unknown)
|
.unwrap_or_else(Type::unknown),
|
||||||
}
|
(Type::SpecialForm(SpecialFormType::Generic), typevar, _) => self
|
||||||
(Type::KnownInstance(KnownInstanceType::Generic(None)), typevar, _) => self
|
|
||||||
.legacy_generic_class_context(
|
.legacy_generic_class_context(
|
||||||
value_node,
|
value_node,
|
||||||
std::slice::from_ref(&typevar),
|
std::slice::from_ref(&typevar),
|
||||||
LegacyGenericBase::Generic,
|
LegacyGenericBase::Generic,
|
||||||
)
|
)
|
||||||
.map(|context| Type::KnownInstance(KnownInstanceType::Generic(Some(context))))
|
.map(|context| Type::KnownInstance(KnownInstanceType::SubscriptedGeneric(context)))
|
||||||
.unwrap_or_else(Type::unknown),
|
.unwrap_or_else(Type::unknown),
|
||||||
(Type::KnownInstance(KnownInstanceType::Generic(Some(_))), _, _) => {
|
(Type::KnownInstance(KnownInstanceType::SubscriptedGeneric(_)), _, _) => {
|
||||||
// TODO: emit a diagnostic
|
// TODO: emit a diagnostic
|
||||||
todo_type!("doubly-specialized typing.Generic")
|
todo_type!("doubly-specialized typing.Generic")
|
||||||
}
|
}
|
||||||
|
(Type::SpecialForm(special_form), _, _) if special_form.class().is_special_form() => {
|
||||||
|
todo_type!("Inference of subscript on special form")
|
||||||
|
}
|
||||||
(Type::KnownInstance(known_instance), _, _)
|
(Type::KnownInstance(known_instance), _, _)
|
||||||
if known_instance.class().is_special_form() =>
|
if known_instance.class().is_special_form() =>
|
||||||
{
|
{
|
||||||
|
@ -7779,10 +7784,10 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
ast::ExprContext::Load => {
|
ast::ExprContext::Load => {
|
||||||
let name_expr_ty = self.infer_name_expression(name);
|
let name_expr_ty = self.infer_name_expression(name);
|
||||||
match name_expr_ty {
|
match name_expr_ty {
|
||||||
Type::KnownInstance(KnownInstanceType::ClassVar) => {
|
Type::SpecialForm(SpecialFormType::ClassVar) => {
|
||||||
TypeAndQualifiers::new(Type::unknown(), TypeQualifiers::CLASS_VAR)
|
TypeAndQualifiers::new(Type::unknown(), TypeQualifiers::CLASS_VAR)
|
||||||
}
|
}
|
||||||
Type::KnownInstance(KnownInstanceType::Final) => {
|
Type::SpecialForm(SpecialFormType::Final) => {
|
||||||
TypeAndQualifiers::new(Type::unknown(), TypeQualifiers::FINAL)
|
TypeAndQualifiers::new(Type::unknown(), TypeQualifiers::FINAL)
|
||||||
}
|
}
|
||||||
_ => name_expr_ty
|
_ => name_expr_ty
|
||||||
|
@ -7809,7 +7814,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
let slice = &**slice;
|
let slice = &**slice;
|
||||||
|
|
||||||
match value_ty {
|
match value_ty {
|
||||||
Type::KnownInstance(KnownInstanceType::Annotated) => {
|
Type::SpecialForm(SpecialFormType::Annotated) => {
|
||||||
// This branch is similar to the corresponding branch in `infer_parameterized_known_instance_type_expression`, but
|
// This branch is similar to the corresponding branch in `infer_parameterized_known_instance_type_expression`, but
|
||||||
// `Annotated[…]` can appear both in annotation expressions and in type expressions, and needs to be handled slightly
|
// `Annotated[…]` can appear both in annotation expressions and in type expressions, and needs to be handled slightly
|
||||||
// differently in each case (calling either `infer_type_expression_*` or `infer_annotation_expression_*`).
|
// differently in each case (calling either `infer_type_expression_*` or `infer_annotation_expression_*`).
|
||||||
|
@ -7818,11 +7823,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}) = slice
|
}) = slice
|
||||||
{
|
{
|
||||||
if arguments.len() < 2 {
|
if arguments.len() < 2 {
|
||||||
report_invalid_arguments_to_annotated(
|
report_invalid_arguments_to_annotated(&self.context, subscript);
|
||||||
self.db(),
|
|
||||||
&self.context,
|
|
||||||
subscript,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let [inner_annotation, metadata @ ..] = &arguments[..] {
|
if let [inner_annotation, metadata @ ..] = &arguments[..] {
|
||||||
|
@ -7840,16 +7841,12 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
TypeAndQualifiers::unknown()
|
TypeAndQualifiers::unknown()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
report_invalid_arguments_to_annotated(
|
report_invalid_arguments_to_annotated(&self.context, subscript);
|
||||||
self.db(),
|
|
||||||
&self.context,
|
|
||||||
subscript,
|
|
||||||
);
|
|
||||||
self.infer_annotation_expression_impl(slice)
|
self.infer_annotation_expression_impl(slice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::KnownInstance(
|
Type::SpecialForm(
|
||||||
known_instance @ (KnownInstanceType::ClassVar | KnownInstanceType::Final),
|
type_qualifier @ (SpecialFormType::ClassVar | SpecialFormType::Final),
|
||||||
) => match slice {
|
) => match slice {
|
||||||
ast::Expr::Tuple(..) => {
|
ast::Expr::Tuple(..) => {
|
||||||
if let Some(builder) =
|
if let Some(builder) =
|
||||||
|
@ -7858,7 +7855,6 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Type qualifier `{type_qualifier}` \
|
"Type qualifier `{type_qualifier}` \
|
||||||
expects exactly one type parameter",
|
expects exactly one type parameter",
|
||||||
type_qualifier = known_instance.repr(self.db()),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Type::unknown().into()
|
Type::unknown().into()
|
||||||
|
@ -7866,11 +7862,11 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
_ => {
|
_ => {
|
||||||
let mut type_and_qualifiers =
|
let mut type_and_qualifiers =
|
||||||
self.infer_annotation_expression_impl(slice);
|
self.infer_annotation_expression_impl(slice);
|
||||||
match known_instance {
|
match type_qualifier {
|
||||||
KnownInstanceType::ClassVar => {
|
SpecialFormType::ClassVar => {
|
||||||
type_and_qualifiers.add_qualifier(TypeQualifiers::CLASS_VAR);
|
type_and_qualifiers.add_qualifier(TypeQualifiers::CLASS_VAR);
|
||||||
}
|
}
|
||||||
KnownInstanceType::Final => {
|
SpecialFormType::Final => {
|
||||||
type_and_qualifiers.add_qualifier(TypeQualifiers::FINAL);
|
type_and_qualifiers.add_qualifier(TypeQualifiers::FINAL);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -8322,7 +8318,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
builder.expression_type(value)
|
builder.expression_type(value)
|
||||||
};
|
};
|
||||||
|
|
||||||
value_ty == Type::KnownInstance(KnownInstanceType::Unpack)
|
value_ty == Type::SpecialForm(SpecialFormType::Unpack)
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -8393,7 +8389,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::KnownInstance(KnownInstanceType::Unknown) => {
|
Type::SpecialForm(SpecialFormType::Unknown) => {
|
||||||
SubclassOfType::subclass_of_unknown()
|
SubclassOfType::subclass_of_unknown()
|
||||||
}
|
}
|
||||||
_ => todo_type!("unsupported type[X] special form"),
|
_ => todo_type!("unsupported type[X] special form"),
|
||||||
|
@ -8424,7 +8420,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let parameters_ty = match self.infer_expression(value) {
|
let parameters_ty = match self.infer_expression(value) {
|
||||||
Type::KnownInstance(KnownInstanceType::Union) => match &**parameters {
|
Type::SpecialForm(SpecialFormType::Union) => match &**parameters {
|
||||||
ast::Expr::Tuple(tuple) => {
|
ast::Expr::Tuple(tuple) => {
|
||||||
let ty = UnionType::from_elements(
|
let ty = UnionType::from_elements(
|
||||||
self.db(),
|
self.db(),
|
||||||
|
@ -8472,9 +8468,37 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
Type::unknown()
|
Type::unknown()
|
||||||
}
|
}
|
||||||
Type::KnownInstance(known_instance) => {
|
Type::SpecialForm(special_form) => {
|
||||||
self.infer_parameterized_known_instance_type_expression(subscript, known_instance)
|
self.infer_parameterized_special_form_type_expression(subscript, special_form)
|
||||||
}
|
}
|
||||||
|
Type::KnownInstance(known_instance) => match known_instance {
|
||||||
|
KnownInstanceType::SubscriptedProtocol(_) => {
|
||||||
|
self.infer_type_expression(&subscript.slice);
|
||||||
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
|
builder.into_diagnostic(format_args!(
|
||||||
|
"`typing.Protocol` is not allowed in type expressions",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Type::unknown()
|
||||||
|
}
|
||||||
|
KnownInstanceType::SubscriptedGeneric(_) => {
|
||||||
|
self.infer_type_expression(&subscript.slice);
|
||||||
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
|
builder.into_diagnostic(format_args!(
|
||||||
|
"`typing.Generic` is not allowed in type expressions",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Type::unknown()
|
||||||
|
}
|
||||||
|
KnownInstanceType::TypeVar(_) => {
|
||||||
|
self.infer_type_expression(&subscript.slice);
|
||||||
|
todo_type!("TypeVar annotations")
|
||||||
|
}
|
||||||
|
KnownInstanceType::TypeAliasType(_) => {
|
||||||
|
self.infer_type_expression(&subscript.slice);
|
||||||
|
todo_type!("Generic PEP-695 type alias")
|
||||||
|
}
|
||||||
|
},
|
||||||
Type::Dynamic(DynamicType::Todo(_)) => {
|
Type::Dynamic(DynamicType::Todo(_)) => {
|
||||||
self.infer_type_expression(slice);
|
self.infer_type_expression(slice);
|
||||||
value_ty
|
value_ty
|
||||||
|
@ -8509,20 +8533,20 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_parameterized_known_instance_type_expression(
|
fn infer_parameterized_special_form_type_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
subscript: &ast::ExprSubscript,
|
subscript: &ast::ExprSubscript,
|
||||||
known_instance: KnownInstanceType,
|
special_form: SpecialFormType,
|
||||||
) -> Type<'db> {
|
) -> Type<'db> {
|
||||||
let db = self.db();
|
let db = self.db();
|
||||||
let arguments_slice = &*subscript.slice;
|
let arguments_slice = &*subscript.slice;
|
||||||
match known_instance {
|
match special_form {
|
||||||
KnownInstanceType::Annotated => {
|
SpecialFormType::Annotated => {
|
||||||
let ast::Expr::Tuple(ast::ExprTuple {
|
let ast::Expr::Tuple(ast::ExprTuple {
|
||||||
elts: arguments, ..
|
elts: arguments, ..
|
||||||
}) = arguments_slice
|
}) = arguments_slice
|
||||||
else {
|
else {
|
||||||
report_invalid_arguments_to_annotated(self.db(), &self.context, subscript);
|
report_invalid_arguments_to_annotated(&self.context, subscript);
|
||||||
|
|
||||||
// `Annotated[]` with less than two arguments is an error at runtime.
|
// `Annotated[]` with less than two arguments is an error at runtime.
|
||||||
// However, we still treat `Annotated[T]` as `T` here for the purpose of
|
// However, we still treat `Annotated[T]` as `T` here for the purpose of
|
||||||
|
@ -8532,7 +8556,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if arguments.len() < 2 {
|
if arguments.len() < 2 {
|
||||||
report_invalid_arguments_to_annotated(self.db(), &self.context, subscript);
|
report_invalid_arguments_to_annotated(&self.context, subscript);
|
||||||
}
|
}
|
||||||
|
|
||||||
let [type_expr, metadata @ ..] = &arguments[..] else {
|
let [type_expr, metadata @ ..] = &arguments[..] else {
|
||||||
|
@ -8548,29 +8572,27 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
self.store_expression_type(arguments_slice, ty);
|
self.store_expression_type(arguments_slice, ty);
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
KnownInstanceType::Literal => {
|
SpecialFormType::Literal => match self.infer_literal_parameter_type(arguments_slice) {
|
||||||
match self.infer_literal_parameter_type(arguments_slice) {
|
|
||||||
Ok(ty) => ty,
|
Ok(ty) => ty,
|
||||||
Err(nodes) => {
|
Err(nodes) => {
|
||||||
for node in nodes {
|
for node in nodes {
|
||||||
if let Some(builder) =
|
let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, node)
|
||||||
self.context.report_lint(&INVALID_TYPE_FORM, node)
|
else {
|
||||||
{
|
continue;
|
||||||
|
};
|
||||||
builder.into_diagnostic(
|
builder.into_diagnostic(
|
||||||
"Type arguments for `Literal` must be `None`, \
|
"Type arguments for `Literal` must be `None`, \
|
||||||
a literal value (int, bool, str, or bytes), or an enum value",
|
a literal value (int, bool, str, or bytes), or an enum value",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Type::unknown()
|
Type::unknown()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
SpecialFormType::Optional => {
|
||||||
KnownInstanceType::Optional => {
|
|
||||||
let param_type = self.infer_type_expression(arguments_slice);
|
let param_type = self.infer_type_expression(arguments_slice);
|
||||||
UnionType::from_elements(db, [param_type, Type::none(db)])
|
UnionType::from_elements(db, [param_type, Type::none(db)])
|
||||||
}
|
}
|
||||||
KnownInstanceType::Union => match arguments_slice {
|
SpecialFormType::Union => match arguments_slice {
|
||||||
ast::Expr::Tuple(t) => {
|
ast::Expr::Tuple(t) => {
|
||||||
let union_ty = UnionType::from_elements(
|
let union_ty = UnionType::from_elements(
|
||||||
db,
|
db,
|
||||||
|
@ -8581,15 +8603,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
_ => self.infer_type_expression(arguments_slice),
|
_ => self.infer_type_expression(arguments_slice),
|
||||||
},
|
},
|
||||||
KnownInstanceType::TypeVar(_) => {
|
SpecialFormType::Callable => {
|
||||||
self.infer_type_expression(arguments_slice);
|
|
||||||
todo_type!("TypeVar annotations")
|
|
||||||
}
|
|
||||||
KnownInstanceType::TypeAliasType(_) => {
|
|
||||||
self.infer_type_expression(arguments_slice);
|
|
||||||
todo_type!("Generic PEP-695 type alias")
|
|
||||||
}
|
|
||||||
KnownInstanceType::Callable => {
|
|
||||||
let mut arguments = match arguments_slice {
|
let mut arguments = match arguments_slice {
|
||||||
ast::Expr::Tuple(tuple) => Either::Left(tuple.iter()),
|
ast::Expr::Tuple(tuple) => Either::Left(tuple.iter()),
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -8616,7 +8630,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if !correct_argument_number {
|
if !correct_argument_number {
|
||||||
report_invalid_arguments_to_callable(self.db(), &self.context, subscript);
|
report_invalid_arguments_to_callable(&self.context, subscript);
|
||||||
}
|
}
|
||||||
|
|
||||||
let callable_type = if let (Some(parameters), Some(return_type), true) =
|
let callable_type = if let (Some(parameters), Some(return_type), true) =
|
||||||
|
@ -8638,12 +8652,11 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type API special forms
|
// Type API special forms
|
||||||
KnownInstanceType::Not => match arguments_slice {
|
SpecialFormType::Not => match arguments_slice {
|
||||||
ast::Expr::Tuple(_) => {
|
ast::Expr::Tuple(_) => {
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Special form `{}` expected exactly one type parameter",
|
"Special form `{special_form}` expected exactly one type parameter",
|
||||||
known_instance.repr(self.db())
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Type::unknown()
|
Type::unknown()
|
||||||
|
@ -8653,7 +8666,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
argument_type.negate(db)
|
argument_type.negate(db)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
KnownInstanceType::Intersection => {
|
SpecialFormType::Intersection => {
|
||||||
let elements = match arguments_slice {
|
let elements = match arguments_slice {
|
||||||
ast::Expr::Tuple(tuple) => Either::Left(tuple.iter()),
|
ast::Expr::Tuple(tuple) => Either::Left(tuple.iter()),
|
||||||
element => Either::Right(std::iter::once(element)),
|
element => Either::Right(std::iter::once(element)),
|
||||||
|
@ -8670,12 +8683,11 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
KnownInstanceType::TypeOf => match arguments_slice {
|
SpecialFormType::TypeOf => match arguments_slice {
|
||||||
ast::Expr::Tuple(_) => {
|
ast::Expr::Tuple(_) => {
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Special form `{}` expected exactly one type parameter",
|
"Special form `{special_form}` expected exactly one type parameter",
|
||||||
known_instance.repr(self.db())
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Type::unknown()
|
Type::unknown()
|
||||||
|
@ -8686,12 +8698,11 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
self.infer_expression(arguments_slice)
|
self.infer_expression(arguments_slice)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
KnownInstanceType::CallableTypeOf => match arguments_slice {
|
SpecialFormType::CallableTypeOf => match arguments_slice {
|
||||||
ast::Expr::Tuple(_) => {
|
ast::Expr::Tuple(_) => {
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Special form `{}` expected exactly one type parameter",
|
"Special form `{special_form}` expected exactly one type parameter",
|
||||||
known_instance.repr(self.db())
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Type::unknown()
|
Type::unknown()
|
||||||
|
@ -8721,11 +8732,10 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
.report_lint(&INVALID_TYPE_FORM, arguments_slice)
|
.report_lint(&INVALID_TYPE_FORM, arguments_slice)
|
||||||
{
|
{
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Expected the first argument to `{}` \
|
"Expected the first argument to `{special_form}` \
|
||||||
to be a callable object, \
|
to be a callable object, \
|
||||||
but got an object of type `{}`",
|
but got an object of type `{actual_type}`",
|
||||||
known_instance.repr(self.db()),
|
actual_type = argument_type.display(db)
|
||||||
argument_type.display(db)
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return Type::unknown();
|
return Type::unknown();
|
||||||
|
@ -8739,142 +8749,129 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: Generics
|
// TODO: Generics
|
||||||
KnownInstanceType::ChainMap => {
|
SpecialFormType::ChainMap => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::ChainMap.to_instance(db)
|
KnownClass::ChainMap.to_instance(db)
|
||||||
}
|
}
|
||||||
KnownInstanceType::OrderedDict => {
|
SpecialFormType::OrderedDict => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::OrderedDict.to_instance(db)
|
KnownClass::OrderedDict.to_instance(db)
|
||||||
}
|
}
|
||||||
KnownInstanceType::Dict => {
|
SpecialFormType::Dict => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::Dict.to_instance(db)
|
KnownClass::Dict.to_instance(db)
|
||||||
}
|
}
|
||||||
KnownInstanceType::List => {
|
SpecialFormType::List => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::List.to_instance(db)
|
KnownClass::List.to_instance(db)
|
||||||
}
|
}
|
||||||
KnownInstanceType::DefaultDict => {
|
SpecialFormType::DefaultDict => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::DefaultDict.to_instance(db)
|
KnownClass::DefaultDict.to_instance(db)
|
||||||
}
|
}
|
||||||
KnownInstanceType::Counter => {
|
SpecialFormType::Counter => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::Counter.to_instance(db)
|
KnownClass::Counter.to_instance(db)
|
||||||
}
|
}
|
||||||
KnownInstanceType::Set => {
|
SpecialFormType::Set => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::Set.to_instance(db)
|
KnownClass::Set.to_instance(db)
|
||||||
}
|
}
|
||||||
KnownInstanceType::FrozenSet => {
|
SpecialFormType::FrozenSet => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::FrozenSet.to_instance(db)
|
KnownClass::FrozenSet.to_instance(db)
|
||||||
}
|
}
|
||||||
KnownInstanceType::Deque => {
|
SpecialFormType::Deque => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
KnownClass::Deque.to_instance(db)
|
KnownClass::Deque.to_instance(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
KnownInstanceType::ReadOnly => {
|
SpecialFormType::ReadOnly => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
todo_type!("`ReadOnly[]` type qualifier")
|
todo_type!("`ReadOnly[]` type qualifier")
|
||||||
}
|
}
|
||||||
KnownInstanceType::NotRequired => {
|
SpecialFormType::NotRequired => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
todo_type!("`NotRequired[]` type qualifier")
|
todo_type!("`NotRequired[]` type qualifier")
|
||||||
}
|
}
|
||||||
KnownInstanceType::ClassVar | KnownInstanceType::Final => {
|
SpecialFormType::ClassVar | SpecialFormType::Final => {
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
let diag = builder.into_diagnostic(format_args!(
|
let diag = builder.into_diagnostic(format_args!(
|
||||||
"Type qualifier `{}` is not allowed in type expressions \
|
"Type qualifier `{special_form}` is not allowed in type expressions \
|
||||||
(only in annotation expressions)",
|
(only in annotation expressions)",
|
||||||
known_instance.repr(self.db())
|
|
||||||
));
|
));
|
||||||
diagnostic::add_type_expression_reference_link(diag);
|
diagnostic::add_type_expression_reference_link(diag);
|
||||||
}
|
}
|
||||||
self.infer_type_expression(arguments_slice)
|
self.infer_type_expression(arguments_slice)
|
||||||
}
|
}
|
||||||
KnownInstanceType::Required => {
|
SpecialFormType::Required => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
todo_type!("`Required[]` type qualifier")
|
todo_type!("`Required[]` type qualifier")
|
||||||
}
|
}
|
||||||
KnownInstanceType::TypeIs => {
|
SpecialFormType::TypeIs => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
todo_type!("`TypeIs[]` special form")
|
todo_type!("`TypeIs[]` special form")
|
||||||
}
|
}
|
||||||
KnownInstanceType::TypeGuard => {
|
SpecialFormType::TypeGuard => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
todo_type!("`TypeGuard[]` special form")
|
todo_type!("`TypeGuard[]` special form")
|
||||||
}
|
}
|
||||||
KnownInstanceType::Concatenate => {
|
SpecialFormType::Concatenate => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
todo_type!("`Concatenate[]` special form")
|
todo_type!("`Concatenate[]` special form")
|
||||||
}
|
}
|
||||||
KnownInstanceType::Unpack => {
|
SpecialFormType::Unpack => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
todo_type!("`Unpack[]` special form")
|
todo_type!("`Unpack[]` special form")
|
||||||
}
|
}
|
||||||
KnownInstanceType::Protocol(_) => {
|
SpecialFormType::NoReturn
|
||||||
self.infer_type_expression(arguments_slice);
|
| SpecialFormType::Never
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
| SpecialFormType::AlwaysTruthy
|
||||||
builder.into_diagnostic(format_args!(
|
| SpecialFormType::AlwaysFalsy => {
|
||||||
"`typing.Protocol` is not allowed in type expressions",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Type::unknown()
|
|
||||||
}
|
|
||||||
KnownInstanceType::Generic(_) => {
|
|
||||||
self.infer_type_expression(arguments_slice);
|
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
|
||||||
builder.into_diagnostic(format_args!(
|
|
||||||
"`typing.Generic` is not allowed in type expressions",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Type::unknown()
|
|
||||||
}
|
|
||||||
KnownInstanceType::NoReturn
|
|
||||||
| KnownInstanceType::Never
|
|
||||||
| KnownInstanceType::AlwaysTruthy
|
|
||||||
| KnownInstanceType::AlwaysFalsy => {
|
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
|
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Type `{}` expected no type parameter",
|
"Type `{special_form}` expected no type parameter",
|
||||||
known_instance.repr(self.db())
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Type::unknown()
|
Type::unknown()
|
||||||
}
|
}
|
||||||
KnownInstanceType::TypingSelf
|
SpecialFormType::TypingSelf
|
||||||
| KnownInstanceType::TypeAlias
|
| SpecialFormType::TypeAlias
|
||||||
| KnownInstanceType::TypedDict
|
| SpecialFormType::TypedDict
|
||||||
| KnownInstanceType::Unknown => {
|
| SpecialFormType::Unknown => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
|
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
builder.into_diagnostic(format_args!(
|
builder.into_diagnostic(format_args!(
|
||||||
"Special form `{}` expected no type parameter",
|
"Special form `{special_form}` expected no type parameter",
|
||||||
known_instance.repr(self.db())
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Type::unknown()
|
Type::unknown()
|
||||||
}
|
}
|
||||||
KnownInstanceType::LiteralString => {
|
SpecialFormType::LiteralString => {
|
||||||
self.infer_type_expression(arguments_slice);
|
self.infer_type_expression(arguments_slice);
|
||||||
|
|
||||||
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
let mut diag = builder.into_diagnostic(format_args!(
|
let mut diag = builder.into_diagnostic(format_args!(
|
||||||
"Type `{}` expected no type parameter",
|
"Type `{special_form}` expected no type parameter",
|
||||||
known_instance.repr(self.db())
|
|
||||||
));
|
));
|
||||||
diag.info("Did you mean to use `Literal[...]` instead?");
|
diag.info("Did you mean to use `Literal[...]` instead?");
|
||||||
}
|
}
|
||||||
Type::unknown()
|
Type::unknown()
|
||||||
}
|
}
|
||||||
KnownInstanceType::Type => self.infer_subclass_of_type_expression(arguments_slice),
|
SpecialFormType::Type => self.infer_subclass_of_type_expression(arguments_slice),
|
||||||
KnownInstanceType::Tuple => self.infer_tuple_type_expression(arguments_slice),
|
SpecialFormType::Tuple => self.infer_tuple_type_expression(arguments_slice),
|
||||||
|
SpecialFormType::Generic | SpecialFormType::Protocol => {
|
||||||
|
self.infer_expression(arguments_slice);
|
||||||
|
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
|
||||||
|
builder.into_diagnostic(format_args!(
|
||||||
|
"`{special_form}` is not allowed in type expressions",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Type::unknown()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8886,7 +8883,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
// TODO handle type aliases
|
// TODO handle type aliases
|
||||||
ast::Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => {
|
ast::Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => {
|
||||||
let value_ty = self.infer_expression(value);
|
let value_ty = self.infer_expression(value);
|
||||||
if matches!(value_ty, Type::KnownInstance(KnownInstanceType::Literal)) {
|
if matches!(value_ty, Type::SpecialForm(SpecialFormType::Literal)) {
|
||||||
let ty = self.infer_literal_parameter_type(slice)?;
|
let ty = self.infer_literal_parameter_type(slice)?;
|
||||||
|
|
||||||
// This branch deals with annotations such as `Literal[Literal[1]]`.
|
// This branch deals with annotations such as `Literal[Literal[1]]`.
|
||||||
|
@ -9427,7 +9424,7 @@ mod tests {
|
||||||
let name_ty = var_ty.member(&db, "__name__").symbol.expect_type();
|
let name_ty = var_ty.member(&db, "__name__").symbol.expect_type();
|
||||||
assert_eq!(name_ty.display(&db).to_string(), expected_name_ty);
|
assert_eq!(name_ty.display(&db).to_string(), expected_name_ty);
|
||||||
|
|
||||||
let KnownInstanceType::TypeVar(typevar) = var_ty.expect_known_instance() else {
|
let Type::KnownInstance(KnownInstanceType::TypeVar(typevar)) = var_ty else {
|
||||||
panic!("expected TypeVar");
|
panic!("expected TypeVar");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,413 +0,0 @@
|
||||||
//! The `KnownInstance` type.
|
|
||||||
//!
|
|
||||||
//! Despite its name, this is quite a different type from [`super::NominalInstanceType`].
|
|
||||||
//! For the vast majority of instance-types in Python, we cannot say how many possible
|
|
||||||
//! inhabitants there are or could be of that type at runtime. Each variant of the
|
|
||||||
//! [`KnownInstanceType`] enum, however, represents a specific runtime symbol
|
|
||||||
//! that requires heavy special-casing in the type system. Thus any one `KnownInstance`
|
|
||||||
//! variant can only be inhabited by one or two specific objects at runtime with
|
|
||||||
//! locations that are known in advance.
|
|
||||||
|
|
||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use super::generics::GenericContext;
|
|
||||||
use super::{ClassType, Type, TypeAliasType, TypeVarInstance, class::KnownClass};
|
|
||||||
use crate::db::Db;
|
|
||||||
use crate::module_resolver::{KnownModule, file_to_module};
|
|
||||||
use ruff_db::files::File;
|
|
||||||
|
|
||||||
/// Enumeration of specific runtime symbols that are special enough
|
|
||||||
/// that they can each be considered to inhabit a unique type.
|
|
||||||
///
|
|
||||||
/// # Ordering
|
|
||||||
///
|
|
||||||
/// Ordering between variants is stable and should be the same between runs.
|
|
||||||
/// Ordering within variants (for variants that wrap associate data)
|
|
||||||
/// is based on the known-instance's salsa-assigned id and not on its values.
|
|
||||||
/// The id may change between runs, or when the type var instance was garbage collected and recreated.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update, PartialOrd, Ord)]
|
|
||||||
pub enum KnownInstanceType<'db> {
|
|
||||||
/// The symbol `typing.Annotated` (which can also be found as `typing_extensions.Annotated`)
|
|
||||||
Annotated,
|
|
||||||
/// The symbol `typing.Literal` (which can also be found as `typing_extensions.Literal`)
|
|
||||||
Literal,
|
|
||||||
/// The symbol `typing.LiteralString` (which can also be found as `typing_extensions.LiteralString`)
|
|
||||||
LiteralString,
|
|
||||||
/// The symbol `typing.Optional` (which can also be found as `typing_extensions.Optional`)
|
|
||||||
Optional,
|
|
||||||
/// The symbol `typing.Union` (which can also be found as `typing_extensions.Union`)
|
|
||||||
Union,
|
|
||||||
/// The symbol `typing.NoReturn` (which can also be found as `typing_extensions.NoReturn`)
|
|
||||||
NoReturn,
|
|
||||||
/// The symbol `typing.Never` available since 3.11 (which can also be found as `typing_extensions.Never`)
|
|
||||||
Never,
|
|
||||||
/// The symbol `typing.Tuple` (which can also be found as `typing_extensions.Tuple`)
|
|
||||||
Tuple,
|
|
||||||
/// The symbol `typing.List` (which can also be found as `typing_extensions.List`)
|
|
||||||
List,
|
|
||||||
/// The symbol `typing.Dict` (which can also be found as `typing_extensions.Dict`)
|
|
||||||
Dict,
|
|
||||||
/// The symbol `typing.Set` (which can also be found as `typing_extensions.Set`)
|
|
||||||
Set,
|
|
||||||
/// The symbol `typing.FrozenSet` (which can also be found as `typing_extensions.FrozenSet`)
|
|
||||||
FrozenSet,
|
|
||||||
/// The symbol `typing.ChainMap` (which can also be found as `typing_extensions.ChainMap`)
|
|
||||||
ChainMap,
|
|
||||||
/// The symbol `typing.Counter` (which can also be found as `typing_extensions.Counter`)
|
|
||||||
Counter,
|
|
||||||
/// The symbol `typing.DefaultDict` (which can also be found as `typing_extensions.DefaultDict`)
|
|
||||||
DefaultDict,
|
|
||||||
/// The symbol `typing.Deque` (which can also be found as `typing_extensions.Deque`)
|
|
||||||
Deque,
|
|
||||||
/// The symbol `typing.OrderedDict` (which can also be found as `typing_extensions.OrderedDict`)
|
|
||||||
OrderedDict,
|
|
||||||
/// The symbol `typing.Protocol` (which can also be found as `typing_extensions.Protocol`)
|
|
||||||
Protocol(Option<GenericContext<'db>>),
|
|
||||||
/// The symbol `typing.Generic` (which can also be found as `typing_extensions.Generic`)
|
|
||||||
Generic(Option<GenericContext<'db>>),
|
|
||||||
/// The symbol `typing.Type` (which can also be found as `typing_extensions.Type`)
|
|
||||||
Type,
|
|
||||||
/// A single instance of `typing.TypeVar`
|
|
||||||
TypeVar(TypeVarInstance<'db>),
|
|
||||||
/// A single instance of `typing.TypeAliasType` (PEP 695 type alias)
|
|
||||||
TypeAliasType(TypeAliasType<'db>),
|
|
||||||
/// The symbol `ty_extensions.Unknown`
|
|
||||||
Unknown,
|
|
||||||
/// The symbol `ty_extensions.AlwaysTruthy`
|
|
||||||
AlwaysTruthy,
|
|
||||||
/// The symbol `ty_extensions.AlwaysFalsy`
|
|
||||||
AlwaysFalsy,
|
|
||||||
/// The symbol `ty_extensions.Not`
|
|
||||||
Not,
|
|
||||||
/// The symbol `ty_extensions.Intersection`
|
|
||||||
Intersection,
|
|
||||||
/// The symbol `ty_extensions.TypeOf`
|
|
||||||
TypeOf,
|
|
||||||
/// The symbol `ty_extensions.CallableTypeOf`
|
|
||||||
CallableTypeOf,
|
|
||||||
/// The symbol `typing.Callable`
|
|
||||||
/// (which can also be found as `typing_extensions.Callable` or as `collections.abc.Callable`)
|
|
||||||
Callable,
|
|
||||||
/// The symbol `typing.Self` (which can also be found as `typing_extensions.Self` or
|
|
||||||
/// `_typeshed.Self`)
|
|
||||||
TypingSelf,
|
|
||||||
|
|
||||||
// Various special forms, special aliases and type qualifiers that we don't yet understand
|
|
||||||
// (all currently inferred as TODO in most contexts):
|
|
||||||
Final,
|
|
||||||
ClassVar,
|
|
||||||
Concatenate,
|
|
||||||
Unpack,
|
|
||||||
Required,
|
|
||||||
NotRequired,
|
|
||||||
TypeAlias,
|
|
||||||
TypeGuard,
|
|
||||||
TypedDict,
|
|
||||||
TypeIs,
|
|
||||||
ReadOnly,
|
|
||||||
// TODO: fill this enum out with more special forms, etc.
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'db> KnownInstanceType<'db> {
|
|
||||||
pub(crate) fn normalized(self, db: &'db dyn Db) -> Self {
|
|
||||||
match self {
|
|
||||||
Self::Annotated
|
|
||||||
| Self::Literal
|
|
||||||
| Self::LiteralString
|
|
||||||
| Self::Optional
|
|
||||||
| Self::Union
|
|
||||||
| Self::NoReturn
|
|
||||||
| Self::Never
|
|
||||||
| Self::Tuple
|
|
||||||
| Self::Type
|
|
||||||
| Self::TypingSelf
|
|
||||||
| Self::Final
|
|
||||||
| Self::ClassVar
|
|
||||||
| Self::Callable
|
|
||||||
| Self::Concatenate
|
|
||||||
| Self::Unpack
|
|
||||||
| Self::Required
|
|
||||||
| Self::NotRequired
|
|
||||||
| Self::TypeAlias
|
|
||||||
| Self::TypeGuard
|
|
||||||
| Self::TypedDict
|
|
||||||
| Self::TypeIs
|
|
||||||
| Self::List
|
|
||||||
| Self::Dict
|
|
||||||
| Self::DefaultDict
|
|
||||||
| Self::Set
|
|
||||||
| Self::FrozenSet
|
|
||||||
| Self::Counter
|
|
||||||
| Self::Deque
|
|
||||||
| Self::ChainMap
|
|
||||||
| Self::OrderedDict
|
|
||||||
| Self::ReadOnly
|
|
||||||
| Self::Unknown
|
|
||||||
| Self::AlwaysTruthy
|
|
||||||
| Self::AlwaysFalsy
|
|
||||||
| Self::Not
|
|
||||||
| Self::Intersection
|
|
||||||
| Self::TypeOf
|
|
||||||
| Self::CallableTypeOf => self,
|
|
||||||
Self::TypeVar(tvar) => Self::TypeVar(tvar.normalized(db)),
|
|
||||||
Self::Protocol(ctx) => Self::Protocol(ctx.map(|ctx| ctx.normalized(db))),
|
|
||||||
Self::Generic(ctx) => Self::Generic(ctx.map(|ctx| ctx.normalized(db))),
|
|
||||||
Self::TypeAliasType(alias) => Self::TypeAliasType(alias.normalized(db)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the repr of the symbol at runtime
|
|
||||||
pub(crate) fn repr(self, db: &'db dyn Db) -> impl Display + 'db {
|
|
||||||
KnownInstanceRepr {
|
|
||||||
known_instance: self,
|
|
||||||
db,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the [`KnownClass`] which this symbol is an instance of
|
|
||||||
pub(crate) const fn class(self) -> KnownClass {
|
|
||||||
match self {
|
|
||||||
Self::Annotated => KnownClass::SpecialForm,
|
|
||||||
Self::Literal => KnownClass::SpecialForm,
|
|
||||||
Self::LiteralString => KnownClass::SpecialForm,
|
|
||||||
Self::Optional => KnownClass::SpecialForm,
|
|
||||||
Self::Union => KnownClass::SpecialForm,
|
|
||||||
Self::NoReturn => KnownClass::SpecialForm,
|
|
||||||
Self::Never => KnownClass::SpecialForm,
|
|
||||||
Self::Tuple => KnownClass::SpecialForm,
|
|
||||||
Self::Type => KnownClass::SpecialForm,
|
|
||||||
Self::TypingSelf => KnownClass::SpecialForm,
|
|
||||||
Self::Final => KnownClass::SpecialForm,
|
|
||||||
Self::ClassVar => KnownClass::SpecialForm,
|
|
||||||
Self::Callable => KnownClass::SpecialForm,
|
|
||||||
Self::Concatenate => KnownClass::SpecialForm,
|
|
||||||
Self::Unpack => KnownClass::SpecialForm,
|
|
||||||
Self::Required => KnownClass::SpecialForm,
|
|
||||||
Self::NotRequired => KnownClass::SpecialForm,
|
|
||||||
Self::TypeAlias => KnownClass::SpecialForm,
|
|
||||||
Self::TypeGuard => KnownClass::SpecialForm,
|
|
||||||
Self::TypedDict => KnownClass::SpecialForm,
|
|
||||||
Self::TypeIs => KnownClass::SpecialForm,
|
|
||||||
Self::ReadOnly => KnownClass::SpecialForm,
|
|
||||||
Self::List => KnownClass::StdlibAlias,
|
|
||||||
Self::Dict => KnownClass::StdlibAlias,
|
|
||||||
Self::DefaultDict => KnownClass::StdlibAlias,
|
|
||||||
Self::Set => KnownClass::StdlibAlias,
|
|
||||||
Self::FrozenSet => KnownClass::StdlibAlias,
|
|
||||||
Self::Counter => KnownClass::StdlibAlias,
|
|
||||||
Self::Deque => KnownClass::StdlibAlias,
|
|
||||||
Self::ChainMap => KnownClass::StdlibAlias,
|
|
||||||
Self::OrderedDict => KnownClass::StdlibAlias,
|
|
||||||
Self::Protocol(_) => KnownClass::SpecialForm, // actually `_ProtocolMeta` at runtime but this is what typeshed says
|
|
||||||
Self::Generic(_) => KnownClass::SpecialForm, // actually `type` at runtime but this is what typeshed says
|
|
||||||
Self::TypeVar(_) => KnownClass::TypeVar,
|
|
||||||
Self::TypeAliasType(_) => KnownClass::TypeAliasType,
|
|
||||||
Self::TypeOf => KnownClass::SpecialForm,
|
|
||||||
Self::Not => KnownClass::SpecialForm,
|
|
||||||
Self::Intersection => KnownClass::SpecialForm,
|
|
||||||
Self::CallableTypeOf => KnownClass::SpecialForm,
|
|
||||||
Self::Unknown => KnownClass::Object,
|
|
||||||
Self::AlwaysTruthy => KnownClass::Object,
|
|
||||||
Self::AlwaysFalsy => KnownClass::Object,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the instance type which this type is a subtype of.
|
|
||||||
///
|
|
||||||
/// For example, the symbol `typing.Literal` is an instance of `typing._SpecialForm`,
|
|
||||||
/// so `KnownInstanceType::Literal.instance_fallback(db)`
|
|
||||||
/// returns `Type::NominalInstance(NominalInstanceType { class: <typing._SpecialForm> })`.
|
|
||||||
pub(super) fn instance_fallback(self, db: &dyn Db) -> Type {
|
|
||||||
self.class().to_instance(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` if this symbol is an instance of `class`.
|
|
||||||
pub(super) fn is_instance_of(self, db: &'db dyn Db, class: ClassType<'db>) -> bool {
|
|
||||||
self.class().is_subclass_of(db, class)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn try_from_file_and_name(
|
|
||||||
db: &'db dyn Db,
|
|
||||||
file: File,
|
|
||||||
symbol_name: &str,
|
|
||||||
) -> Option<Self> {
|
|
||||||
let candidate = match symbol_name {
|
|
||||||
"ClassVar" => Self::ClassVar,
|
|
||||||
"Deque" => Self::Deque,
|
|
||||||
"List" => Self::List,
|
|
||||||
"Dict" => Self::Dict,
|
|
||||||
"DefaultDict" => Self::DefaultDict,
|
|
||||||
"Set" => Self::Set,
|
|
||||||
"FrozenSet" => Self::FrozenSet,
|
|
||||||
"Counter" => Self::Counter,
|
|
||||||
"ChainMap" => Self::ChainMap,
|
|
||||||
"OrderedDict" => Self::OrderedDict,
|
|
||||||
"Generic" => Self::Generic(None),
|
|
||||||
"Protocol" => Self::Protocol(None),
|
|
||||||
"Optional" => Self::Optional,
|
|
||||||
"Union" => Self::Union,
|
|
||||||
"NoReturn" => Self::NoReturn,
|
|
||||||
"Tuple" => Self::Tuple,
|
|
||||||
"Type" => Self::Type,
|
|
||||||
"Callable" => Self::Callable,
|
|
||||||
"Annotated" => Self::Annotated,
|
|
||||||
"Literal" => Self::Literal,
|
|
||||||
"Never" => Self::Never,
|
|
||||||
"Self" => Self::TypingSelf,
|
|
||||||
"Final" => Self::Final,
|
|
||||||
"Unpack" => Self::Unpack,
|
|
||||||
"Required" => Self::Required,
|
|
||||||
"TypeAlias" => Self::TypeAlias,
|
|
||||||
"TypeGuard" => Self::TypeGuard,
|
|
||||||
"TypedDict" => Self::TypedDict,
|
|
||||||
"TypeIs" => Self::TypeIs,
|
|
||||||
"ReadOnly" => Self::ReadOnly,
|
|
||||||
"Concatenate" => Self::Concatenate,
|
|
||||||
"NotRequired" => Self::NotRequired,
|
|
||||||
"LiteralString" => Self::LiteralString,
|
|
||||||
"Unknown" => Self::Unknown,
|
|
||||||
"AlwaysTruthy" => Self::AlwaysTruthy,
|
|
||||||
"AlwaysFalsy" => Self::AlwaysFalsy,
|
|
||||||
"Not" => Self::Not,
|
|
||||||
"Intersection" => Self::Intersection,
|
|
||||||
"TypeOf" => Self::TypeOf,
|
|
||||||
"CallableTypeOf" => Self::CallableTypeOf,
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
candidate
|
|
||||||
.check_module(file_to_module(db, file)?.known()?)
|
|
||||||
.then_some(candidate)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` if `module` is a module from which this `KnownInstance` variant can validly originate.
|
|
||||||
///
|
|
||||||
/// Most variants can only exist in one module, which is the same as `self.class().canonical_module()`.
|
|
||||||
/// Some variants could validly be defined in either `typing` or `typing_extensions`, however.
|
|
||||||
pub(super) fn check_module(self, module: KnownModule) -> bool {
|
|
||||||
match self {
|
|
||||||
Self::ClassVar
|
|
||||||
| Self::Deque
|
|
||||||
| Self::List
|
|
||||||
| Self::Dict
|
|
||||||
| Self::DefaultDict
|
|
||||||
| Self::Set
|
|
||||||
| Self::FrozenSet
|
|
||||||
| Self::Counter
|
|
||||||
| Self::ChainMap
|
|
||||||
| Self::OrderedDict
|
|
||||||
| Self::Optional
|
|
||||||
| Self::Union
|
|
||||||
| Self::NoReturn
|
|
||||||
| Self::Tuple
|
|
||||||
| Self::Type
|
|
||||||
| Self::Generic(_)
|
|
||||||
| Self::Callable => module.is_typing(),
|
|
||||||
Self::Annotated
|
|
||||||
| Self::Protocol(_)
|
|
||||||
| Self::Literal
|
|
||||||
| Self::LiteralString
|
|
||||||
| Self::Never
|
|
||||||
| Self::Final
|
|
||||||
| Self::Concatenate
|
|
||||||
| Self::Unpack
|
|
||||||
| Self::Required
|
|
||||||
| Self::NotRequired
|
|
||||||
| Self::TypeAlias
|
|
||||||
| Self::TypeGuard
|
|
||||||
| Self::TypedDict
|
|
||||||
| Self::TypeIs
|
|
||||||
| Self::ReadOnly
|
|
||||||
| Self::TypeAliasType(_)
|
|
||||||
| Self::TypeVar(_) => {
|
|
||||||
matches!(module, KnownModule::Typing | KnownModule::TypingExtensions)
|
|
||||||
}
|
|
||||||
Self::TypingSelf => {
|
|
||||||
matches!(
|
|
||||||
module,
|
|
||||||
KnownModule::Typing | KnownModule::TypingExtensions | KnownModule::Typeshed
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Self::Unknown
|
|
||||||
| Self::AlwaysTruthy
|
|
||||||
| Self::AlwaysFalsy
|
|
||||||
| Self::Not
|
|
||||||
| Self::Intersection
|
|
||||||
| Self::TypeOf
|
|
||||||
| Self::CallableTypeOf => module.is_ty_extensions(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn to_meta_type(self, db: &'db dyn Db) -> Type<'db> {
|
|
||||||
self.class().to_class_literal(db)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct KnownInstanceRepr<'db> {
|
|
||||||
known_instance: KnownInstanceType<'db>,
|
|
||||||
db: &'db dyn Db,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for KnownInstanceRepr<'_> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self.known_instance {
|
|
||||||
KnownInstanceType::Annotated => f.write_str("typing.Annotated"),
|
|
||||||
KnownInstanceType::Literal => f.write_str("typing.Literal"),
|
|
||||||
KnownInstanceType::LiteralString => f.write_str("typing.LiteralString"),
|
|
||||||
KnownInstanceType::Optional => f.write_str("typing.Optional"),
|
|
||||||
KnownInstanceType::Union => f.write_str("typing.Union"),
|
|
||||||
KnownInstanceType::NoReturn => f.write_str("typing.NoReturn"),
|
|
||||||
KnownInstanceType::Never => f.write_str("typing.Never"),
|
|
||||||
KnownInstanceType::Tuple => f.write_str("typing.Tuple"),
|
|
||||||
KnownInstanceType::Type => f.write_str("typing.Type"),
|
|
||||||
KnownInstanceType::TypingSelf => f.write_str("typing.Self"),
|
|
||||||
KnownInstanceType::Final => f.write_str("typing.Final"),
|
|
||||||
KnownInstanceType::ClassVar => f.write_str("typing.ClassVar"),
|
|
||||||
KnownInstanceType::Callable => f.write_str("typing.Callable"),
|
|
||||||
KnownInstanceType::Concatenate => f.write_str("typing.Concatenate"),
|
|
||||||
KnownInstanceType::Unpack => f.write_str("typing.Unpack"),
|
|
||||||
KnownInstanceType::Required => f.write_str("typing.Required"),
|
|
||||||
KnownInstanceType::NotRequired => f.write_str("typing.NotRequired"),
|
|
||||||
KnownInstanceType::TypeAlias => f.write_str("typing.TypeAlias"),
|
|
||||||
KnownInstanceType::TypeGuard => f.write_str("typing.TypeGuard"),
|
|
||||||
KnownInstanceType::TypedDict => f.write_str("typing.TypedDict"),
|
|
||||||
KnownInstanceType::TypeIs => f.write_str("typing.TypeIs"),
|
|
||||||
KnownInstanceType::List => f.write_str("typing.List"),
|
|
||||||
KnownInstanceType::Dict => f.write_str("typing.Dict"),
|
|
||||||
KnownInstanceType::DefaultDict => f.write_str("typing.DefaultDict"),
|
|
||||||
KnownInstanceType::Set => f.write_str("typing.Set"),
|
|
||||||
KnownInstanceType::FrozenSet => f.write_str("typing.FrozenSet"),
|
|
||||||
KnownInstanceType::Counter => f.write_str("typing.Counter"),
|
|
||||||
KnownInstanceType::Deque => f.write_str("typing.Deque"),
|
|
||||||
KnownInstanceType::ChainMap => f.write_str("typing.ChainMap"),
|
|
||||||
KnownInstanceType::OrderedDict => f.write_str("typing.OrderedDict"),
|
|
||||||
KnownInstanceType::Protocol(generic_context) => {
|
|
||||||
f.write_str("typing.Protocol")?;
|
|
||||||
if let Some(generic_context) = generic_context {
|
|
||||||
generic_context.display(self.db).fmt(f)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
KnownInstanceType::Generic(generic_context) => {
|
|
||||||
f.write_str("typing.Generic")?;
|
|
||||||
if let Some(generic_context) = generic_context {
|
|
||||||
generic_context.display(self.db).fmt(f)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
KnownInstanceType::ReadOnly => f.write_str("typing.ReadOnly"),
|
|
||||||
// This is a legacy `TypeVar` _outside_ of any generic class or function, so we render
|
|
||||||
// it as an instance of `typing.TypeVar`. Inside of a generic class or function, we'll
|
|
||||||
// have a `Type::TypeVar(_)`, which is rendered as the typevar's name.
|
|
||||||
KnownInstanceType::TypeVar(_) => f.write_str("typing.TypeVar"),
|
|
||||||
KnownInstanceType::TypeAliasType(_) => f.write_str("typing.TypeAliasType"),
|
|
||||||
KnownInstanceType::Unknown => f.write_str("ty_extensions.Unknown"),
|
|
||||||
KnownInstanceType::AlwaysTruthy => f.write_str("ty_extensions.AlwaysTruthy"),
|
|
||||||
KnownInstanceType::AlwaysFalsy => f.write_str("ty_extensions.AlwaysFalsy"),
|
|
||||||
KnownInstanceType::Not => f.write_str("ty_extensions.Not"),
|
|
||||||
KnownInstanceType::Intersection => f.write_str("ty_extensions.Intersection"),
|
|
||||||
KnownInstanceType::TypeOf => f.write_str("ty_extensions.TypeOf"),
|
|
||||||
KnownInstanceType::CallableTypeOf => f.write_str("ty_extensions.CallableTypeOf"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ use rustc_hash::FxBuildHasher;
|
||||||
use crate::Db;
|
use crate::Db;
|
||||||
use crate::types::class_base::ClassBase;
|
use crate::types::class_base::ClassBase;
|
||||||
use crate::types::generics::Specialization;
|
use crate::types::generics::Specialization;
|
||||||
use crate::types::{ClassLiteral, ClassType, KnownInstanceType, Type};
|
use crate::types::{ClassLiteral, ClassType, KnownInstanceType, SpecialFormType, Type};
|
||||||
|
|
||||||
/// The inferred method resolution order of a given class.
|
/// The inferred method resolution order of a given class.
|
||||||
///
|
///
|
||||||
|
@ -92,7 +92,7 @@ impl<'db> Mro<'db> {
|
||||||
original_bases: &[Type<'db>],
|
original_bases: &[Type<'db>],
|
||||||
remaining_bases: &[Type<'db>],
|
remaining_bases: &[Type<'db>],
|
||||||
) {
|
) {
|
||||||
if original_bases.contains(&Type::KnownInstance(KnownInstanceType::Protocol(None))) {
|
if original_bases.contains(&Type::SpecialForm(SpecialFormType::Protocol)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if remaining_bases.iter().any(Type::is_generic_alias) {
|
if remaining_bases.iter().any(Type::is_generic_alias) {
|
||||||
|
@ -146,7 +146,8 @@ impl<'db> Mro<'db> {
|
||||||
single_base,
|
single_base,
|
||||||
Type::GenericAlias(_)
|
Type::GenericAlias(_)
|
||||||
| Type::KnownInstance(
|
| Type::KnownInstance(
|
||||||
KnownInstanceType::Generic(_) | KnownInstanceType::Protocol(_)
|
KnownInstanceType::SubscriptedGeneric(_)
|
||||||
|
| KnownInstanceType::SubscriptedProtocol(_)
|
||||||
)
|
)
|
||||||
) =>
|
) =>
|
||||||
{
|
{
|
||||||
|
@ -178,7 +179,7 @@ impl<'db> Mro<'db> {
|
||||||
// (see `infer::TypeInferenceBuilder::check_class_definitions`),
|
// (see `infer::TypeInferenceBuilder::check_class_definitions`),
|
||||||
// which is why we only care about `KnownInstanceType::Generic(Some(_))`,
|
// which is why we only care about `KnownInstanceType::Generic(Some(_))`,
|
||||||
// not `KnownInstanceType::Generic(None)`.
|
// not `KnownInstanceType::Generic(None)`.
|
||||||
if let Type::KnownInstance(KnownInstanceType::Generic(Some(_))) = base {
|
if let Type::KnownInstance(KnownInstanceType::SubscriptedGeneric(_)) = base {
|
||||||
maybe_add_generic(
|
maybe_add_generic(
|
||||||
&mut resolved_bases,
|
&mut resolved_bases,
|
||||||
original_bases,
|
original_bases,
|
||||||
|
@ -226,7 +227,11 @@ impl<'db> Mro<'db> {
|
||||||
|
|
||||||
if class.has_pep_695_type_params(db)
|
if class.has_pep_695_type_params(db)
|
||||||
&& original_bases.iter().any(|base| {
|
&& original_bases.iter().any(|base| {
|
||||||
matches!(base, Type::KnownInstance(KnownInstanceType::Generic(_)))
|
matches!(
|
||||||
|
base,
|
||||||
|
Type::KnownInstance(KnownInstanceType::SubscriptedGeneric(_))
|
||||||
|
| Type::SpecialForm(SpecialFormType::Generic)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
return Err(MroErrorKind::Pep695ClassWithGenericInheritance);
|
return Err(MroErrorKind::Pep695ClassWithGenericInheritance);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::db::tests::TestDb;
|
use crate::db::tests::TestDb;
|
||||||
use crate::symbol::{builtins_symbol, known_module_symbol};
|
use crate::symbol::{builtins_symbol, known_module_symbol};
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
BoundMethodType, CallableType, IntersectionBuilder, KnownClass, KnownInstanceType, Parameter,
|
BoundMethodType, CallableType, IntersectionBuilder, KnownClass, Parameter, Parameters,
|
||||||
Parameters, Signature, SubclassOfType, TupleType, Type, UnionType,
|
Signature, SpecialFormType, SubclassOfType, TupleType, Type, UnionType,
|
||||||
};
|
};
|
||||||
use crate::{Db, KnownModule};
|
use crate::{Db, KnownModule};
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
@ -142,7 +142,7 @@ impl Ty {
|
||||||
Ty::AbcClassLiteral(s) => known_module_symbol(db, KnownModule::Abc, s)
|
Ty::AbcClassLiteral(s) => known_module_symbol(db, KnownModule::Abc, s)
|
||||||
.symbol
|
.symbol
|
||||||
.expect_type(),
|
.expect_type(),
|
||||||
Ty::TypingLiteral => Type::KnownInstance(KnownInstanceType::Literal),
|
Ty::TypingLiteral => Type::SpecialForm(SpecialFormType::Literal),
|
||||||
Ty::BuiltinClassLiteral(s) => builtins_symbol(db, s).symbol.expect_type(),
|
Ty::BuiltinClassLiteral(s) => builtins_symbol(db, s).symbol.expect_type(),
|
||||||
Ty::KnownClassInstance(known_class) => known_class.to_instance(db),
|
Ty::KnownClassInstance(known_class) => known_class.to_instance(db),
|
||||||
Ty::Union(tys) => {
|
Ty::Union(tys) => {
|
||||||
|
|
305
crates/ty_python_semantic/src/types/special_form.rs
Normal file
305
crates/ty_python_semantic/src/types/special_form.rs
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
//! An enumeration of special forms in the Python type system.
|
||||||
|
//! Each of these is considered to inhabit a unique type in our model of the type system.
|
||||||
|
|
||||||
|
use super::{ClassType, Type, class::KnownClass};
|
||||||
|
use crate::db::Db;
|
||||||
|
use crate::module_resolver::{KnownModule, file_to_module};
|
||||||
|
use ruff_db::files::File;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
/// Enumeration of specific runtime symbols that are special enough
|
||||||
|
/// that they can each be considered to inhabit a unique type.
|
||||||
|
///
|
||||||
|
/// # Ordering
|
||||||
|
///
|
||||||
|
/// Ordering is stable and should be the same between runs.
|
||||||
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
salsa::Update,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
strum_macros::EnumString,
|
||||||
|
)]
|
||||||
|
pub enum SpecialFormType {
|
||||||
|
/// The symbol `typing.Annotated` (which can also be found as `typing_extensions.Annotated`)
|
||||||
|
Annotated,
|
||||||
|
/// The symbol `typing.Literal` (which can also be found as `typing_extensions.Literal`)
|
||||||
|
Literal,
|
||||||
|
/// The symbol `typing.LiteralString` (which can also be found as `typing_extensions.LiteralString`)
|
||||||
|
LiteralString,
|
||||||
|
/// The symbol `typing.Optional` (which can also be found as `typing_extensions.Optional`)
|
||||||
|
Optional,
|
||||||
|
/// The symbol `typing.Union` (which can also be found as `typing_extensions.Union`)
|
||||||
|
Union,
|
||||||
|
/// The symbol `typing.NoReturn` (which can also be found as `typing_extensions.NoReturn`)
|
||||||
|
NoReturn,
|
||||||
|
/// The symbol `typing.Never` available since 3.11 (which can also be found as `typing_extensions.Never`)
|
||||||
|
Never,
|
||||||
|
/// The symbol `typing.Tuple` (which can also be found as `typing_extensions.Tuple`)
|
||||||
|
Tuple,
|
||||||
|
/// The symbol `typing.List` (which can also be found as `typing_extensions.List`)
|
||||||
|
List,
|
||||||
|
/// The symbol `typing.Dict` (which can also be found as `typing_extensions.Dict`)
|
||||||
|
Dict,
|
||||||
|
/// The symbol `typing.Set` (which can also be found as `typing_extensions.Set`)
|
||||||
|
Set,
|
||||||
|
/// The symbol `typing.FrozenSet` (which can also be found as `typing_extensions.FrozenSet`)
|
||||||
|
FrozenSet,
|
||||||
|
/// The symbol `typing.ChainMap` (which can also be found as `typing_extensions.ChainMap`)
|
||||||
|
ChainMap,
|
||||||
|
/// The symbol `typing.Counter` (which can also be found as `typing_extensions.Counter`)
|
||||||
|
Counter,
|
||||||
|
/// The symbol `typing.DefaultDict` (which can also be found as `typing_extensions.DefaultDict`)
|
||||||
|
DefaultDict,
|
||||||
|
/// The symbol `typing.Deque` (which can also be found as `typing_extensions.Deque`)
|
||||||
|
Deque,
|
||||||
|
/// The symbol `typing.OrderedDict` (which can also be found as `typing_extensions.OrderedDict`)
|
||||||
|
OrderedDict,
|
||||||
|
/// The symbol `typing.Type` (which can also be found as `typing_extensions.Type`)
|
||||||
|
Type,
|
||||||
|
/// The symbol `ty_extensions.Unknown`
|
||||||
|
Unknown,
|
||||||
|
/// The symbol `ty_extensions.AlwaysTruthy`
|
||||||
|
AlwaysTruthy,
|
||||||
|
/// The symbol `ty_extensions.AlwaysFalsy`
|
||||||
|
AlwaysFalsy,
|
||||||
|
/// The symbol `ty_extensions.Not`
|
||||||
|
Not,
|
||||||
|
/// The symbol `ty_extensions.Intersection`
|
||||||
|
Intersection,
|
||||||
|
/// The symbol `ty_extensions.TypeOf`
|
||||||
|
TypeOf,
|
||||||
|
/// The symbol `ty_extensions.CallableTypeOf`
|
||||||
|
CallableTypeOf,
|
||||||
|
/// The symbol `typing.Callable`
|
||||||
|
/// (which can also be found as `typing_extensions.Callable` or as `collections.abc.Callable`)
|
||||||
|
Callable,
|
||||||
|
/// The symbol `typing.Self` (which can also be found as `typing_extensions.Self` or `_typeshed.Self`)
|
||||||
|
#[strum(serialize = "Self")]
|
||||||
|
TypingSelf,
|
||||||
|
/// The symbol `typing.Final` (which can also be found as `typing_extensions.Final`)
|
||||||
|
Final,
|
||||||
|
/// The symbol `typing.ClassVar` (which can also be found as `typing_extensions.ClassVar`)
|
||||||
|
ClassVar,
|
||||||
|
/// The symbol `typing.Concatenate` (which can also be found as `typing_extensions.Concatenate`)
|
||||||
|
Concatenate,
|
||||||
|
/// The symbol `typing.Unpack` (which can also be found as `typing_extensions.Unpack`)
|
||||||
|
Unpack,
|
||||||
|
/// The symbol `typing.Required` (which can also be found as `typing_extensions.Required`)
|
||||||
|
Required,
|
||||||
|
/// The symbol `typing.NotRequired` (which can also be found as `typing_extensions.NotRequired`)
|
||||||
|
NotRequired,
|
||||||
|
/// The symbol `typing.TypeAlias` (which can also be found as `typing_extensions.TypeAlias`)
|
||||||
|
TypeAlias,
|
||||||
|
/// The symbol `typing.TypeGuard` (which can also be found as `typing_extensions.TypeGuard`)
|
||||||
|
TypeGuard,
|
||||||
|
/// The symbol `typing.TypedDict` (which can also be found as `typing_extensions.TypedDict`)
|
||||||
|
TypedDict,
|
||||||
|
/// The symbol `typing.TypeIs` (which can also be found as `typing_extensions.TypeIs`)
|
||||||
|
TypeIs,
|
||||||
|
/// The symbol `typing.ReadOnly` (which can also be found as `typing_extensions.ReadOnly`)
|
||||||
|
ReadOnly,
|
||||||
|
|
||||||
|
/// The symbol `typing.Protocol` (which can also be found as `typing_extensions.Protocol`)
|
||||||
|
///
|
||||||
|
/// Note that instances of subscripted `typing.Protocol` are not represented by this type;
|
||||||
|
/// see also [`super::KnownInstanceType::SubscriptedProtocol`].
|
||||||
|
Protocol,
|
||||||
|
|
||||||
|
/// The symbol `typing.Generic` (which can also be found as `typing_extensions.Generic`).
|
||||||
|
///
|
||||||
|
/// Note that instances of subscripted `typing.Generic` are not represented by this type;
|
||||||
|
/// see also [`super::KnownInstanceType::SubscriptedGeneric`].
|
||||||
|
Generic,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpecialFormType {
|
||||||
|
/// Return the [`KnownClass`] which this symbol is an instance of
|
||||||
|
pub(crate) const fn class(self) -> KnownClass {
|
||||||
|
match self {
|
||||||
|
Self::Annotated
|
||||||
|
| Self::Literal
|
||||||
|
| Self::LiteralString
|
||||||
|
| Self::Optional
|
||||||
|
| Self::Union
|
||||||
|
| Self::NoReturn
|
||||||
|
| Self::Never
|
||||||
|
| Self::Tuple
|
||||||
|
| Self::Type
|
||||||
|
| Self::TypingSelf
|
||||||
|
| Self::Final
|
||||||
|
| Self::ClassVar
|
||||||
|
| Self::Callable
|
||||||
|
| Self::Concatenate
|
||||||
|
| Self::Unpack
|
||||||
|
| Self::Required
|
||||||
|
| Self::NotRequired
|
||||||
|
| Self::TypeAlias
|
||||||
|
| Self::TypeGuard
|
||||||
|
| Self::TypedDict
|
||||||
|
| Self::TypeIs
|
||||||
|
| Self::TypeOf
|
||||||
|
| Self::Not
|
||||||
|
| Self::Intersection
|
||||||
|
| Self::CallableTypeOf
|
||||||
|
| Self::Protocol // actually `_ProtocolMeta` at runtime but this is what typeshed says
|
||||||
|
| Self::Generic // actually `type` at runtime but this is what typeshed says
|
||||||
|
| Self::ReadOnly => KnownClass::SpecialForm,
|
||||||
|
|
||||||
|
Self::List
|
||||||
|
| Self::Dict
|
||||||
|
| Self::DefaultDict
|
||||||
|
| Self::Set
|
||||||
|
| Self::FrozenSet
|
||||||
|
| Self::Counter
|
||||||
|
| Self::Deque
|
||||||
|
| Self::ChainMap
|
||||||
|
| Self::OrderedDict => KnownClass::StdlibAlias,
|
||||||
|
|
||||||
|
Self::Unknown | Self::AlwaysTruthy | Self::AlwaysFalsy => KnownClass::Object,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the instance type which this type is a subtype of.
|
||||||
|
///
|
||||||
|
/// For example, the symbol `typing.Literal` is an instance of `typing._SpecialForm`,
|
||||||
|
/// so `SpecialFormType::Literal.instance_fallback(db)`
|
||||||
|
/// returns `Type::NominalInstance(NominalInstanceType { class: <typing._SpecialForm> })`.
|
||||||
|
pub(super) fn instance_fallback(self, db: &dyn Db) -> Type {
|
||||||
|
self.class().to_instance(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if this symbol is an instance of `class`.
|
||||||
|
pub(super) fn is_instance_of(self, db: &dyn Db, class: ClassType) -> bool {
|
||||||
|
self.class().is_subclass_of(db, class)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn try_from_file_and_name(
|
||||||
|
db: &dyn Db,
|
||||||
|
file: File,
|
||||||
|
symbol_name: &str,
|
||||||
|
) -> Option<Self> {
|
||||||
|
let candidate = Self::from_str(symbol_name).ok()?;
|
||||||
|
candidate
|
||||||
|
.check_module(file_to_module(db, file)?.known()?)
|
||||||
|
.then_some(candidate)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if `module` is a module from which this `SpecialFormType` variant can validly originate.
|
||||||
|
///
|
||||||
|
/// Most variants can only exist in one module, which is the same as `self.class().canonical_module(db)`.
|
||||||
|
/// Some variants could validly be defined in either `typing` or `typing_extensions`, however.
|
||||||
|
pub(super) fn check_module(self, module: KnownModule) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::ClassVar
|
||||||
|
| Self::Deque
|
||||||
|
| Self::List
|
||||||
|
| Self::Dict
|
||||||
|
| Self::DefaultDict
|
||||||
|
| Self::Set
|
||||||
|
| Self::FrozenSet
|
||||||
|
| Self::Counter
|
||||||
|
| Self::ChainMap
|
||||||
|
| Self::OrderedDict
|
||||||
|
| Self::Optional
|
||||||
|
| Self::Union
|
||||||
|
| Self::NoReturn
|
||||||
|
| Self::Tuple
|
||||||
|
| Self::Type
|
||||||
|
| Self::Generic
|
||||||
|
| Self::Callable => module.is_typing(),
|
||||||
|
|
||||||
|
Self::Annotated
|
||||||
|
| Self::Literal
|
||||||
|
| Self::LiteralString
|
||||||
|
| Self::Never
|
||||||
|
| Self::Final
|
||||||
|
| Self::Concatenate
|
||||||
|
| Self::Unpack
|
||||||
|
| Self::Required
|
||||||
|
| Self::NotRequired
|
||||||
|
| Self::TypeAlias
|
||||||
|
| Self::TypeGuard
|
||||||
|
| Self::TypedDict
|
||||||
|
| Self::TypeIs
|
||||||
|
| Self::Protocol
|
||||||
|
| Self::ReadOnly => {
|
||||||
|
matches!(module, KnownModule::Typing | KnownModule::TypingExtensions)
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::TypingSelf => matches!(
|
||||||
|
module,
|
||||||
|
KnownModule::Typing | KnownModule::TypingExtensions | KnownModule::Typeshed
|
||||||
|
),
|
||||||
|
|
||||||
|
Self::Unknown
|
||||||
|
| Self::AlwaysTruthy
|
||||||
|
| Self::AlwaysFalsy
|
||||||
|
| Self::Not
|
||||||
|
| Self::Intersection
|
||||||
|
| Self::TypeOf
|
||||||
|
| Self::CallableTypeOf => module.is_ty_extensions(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn to_meta_type(self, db: &dyn Db) -> Type {
|
||||||
|
self.class().to_class_literal(db)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the repr of the symbol at runtime
|
||||||
|
pub(super) const fn repr(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
SpecialFormType::Annotated => "typing.Annotated",
|
||||||
|
SpecialFormType::Literal => "typing.Literal",
|
||||||
|
SpecialFormType::LiteralString => "typing.LiteralString",
|
||||||
|
SpecialFormType::Optional => "typing.Optional",
|
||||||
|
SpecialFormType::Union => "typing.Union",
|
||||||
|
SpecialFormType::NoReturn => "typing.NoReturn",
|
||||||
|
SpecialFormType::Never => "typing.Never",
|
||||||
|
SpecialFormType::Tuple => "typing.Tuple",
|
||||||
|
SpecialFormType::Type => "typing.Type",
|
||||||
|
SpecialFormType::TypingSelf => "typing.Self",
|
||||||
|
SpecialFormType::Final => "typing.Final",
|
||||||
|
SpecialFormType::ClassVar => "typing.ClassVar",
|
||||||
|
SpecialFormType::Callable => "typing.Callable",
|
||||||
|
SpecialFormType::Concatenate => "typing.Concatenate",
|
||||||
|
SpecialFormType::Unpack => "typing.Unpack",
|
||||||
|
SpecialFormType::Required => "typing.Required",
|
||||||
|
SpecialFormType::NotRequired => "typing.NotRequired",
|
||||||
|
SpecialFormType::TypeAlias => "typing.TypeAlias",
|
||||||
|
SpecialFormType::TypeGuard => "typing.TypeGuard",
|
||||||
|
SpecialFormType::TypedDict => "typing.TypedDict",
|
||||||
|
SpecialFormType::TypeIs => "typing.TypeIs",
|
||||||
|
SpecialFormType::List => "typing.List",
|
||||||
|
SpecialFormType::Dict => "typing.Dict",
|
||||||
|
SpecialFormType::DefaultDict => "typing.DefaultDict",
|
||||||
|
SpecialFormType::Set => "typing.Set",
|
||||||
|
SpecialFormType::FrozenSet => "typing.FrozenSet",
|
||||||
|
SpecialFormType::Counter => "typing.Counter",
|
||||||
|
SpecialFormType::Deque => "typing.Deque",
|
||||||
|
SpecialFormType::ChainMap => "typing.ChainMap",
|
||||||
|
SpecialFormType::OrderedDict => "typing.OrderedDict",
|
||||||
|
SpecialFormType::ReadOnly => "typing.ReadOnly",
|
||||||
|
SpecialFormType::Unknown => "ty_extensions.Unknown",
|
||||||
|
SpecialFormType::AlwaysTruthy => "ty_extensions.AlwaysTruthy",
|
||||||
|
SpecialFormType::AlwaysFalsy => "ty_extensions.AlwaysFalsy",
|
||||||
|
SpecialFormType::Not => "ty_extensions.Not",
|
||||||
|
SpecialFormType::Intersection => "ty_extensions.Intersection",
|
||||||
|
SpecialFormType::TypeOf => "ty_extensions.TypeOf",
|
||||||
|
SpecialFormType::CallableTypeOf => "ty_extensions.CallableTypeOf",
|
||||||
|
SpecialFormType::Protocol => "typing.Protocol",
|
||||||
|
SpecialFormType::Generic => "typing.Generic",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for SpecialFormType {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(self.repr())
|
||||||
|
}
|
||||||
|
}
|
|
@ -179,10 +179,11 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
|
||||||
(Type::BoundSuper(_), _) => Ordering::Less,
|
(Type::BoundSuper(_), _) => Ordering::Less,
|
||||||
(_, Type::BoundSuper(_)) => Ordering::Greater,
|
(_, Type::BoundSuper(_)) => Ordering::Greater,
|
||||||
|
|
||||||
(Type::KnownInstance(left_instance), Type::KnownInstance(right_instance)) => {
|
(Type::SpecialForm(left), Type::SpecialForm(right)) => left.cmp(right),
|
||||||
left_instance.cmp(right_instance)
|
(Type::SpecialForm(_), _) => Ordering::Less,
|
||||||
}
|
(_, Type::SpecialForm(_)) => Ordering::Greater,
|
||||||
|
|
||||||
|
(Type::KnownInstance(left), Type::KnownInstance(right)) => left.cmp(right),
|
||||||
(Type::KnownInstance(_), _) => Ordering::Less,
|
(Type::KnownInstance(_), _) => Ordering::Less,
|
||||||
(_, Type::KnownInstance(_)) => Ordering::Greater,
|
(_, Type::KnownInstance(_)) => Ordering::Greater,
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue