mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-01 12:25:45 +00:00
[ty] Fix further issues in super() inference logic (#20843)
This commit is contained in:
parent
441ba20876
commit
9090aead0f
5 changed files with 212 additions and 142 deletions
|
|
@ -25,6 +25,8 @@ python-version = "3.12"
|
||||||
```
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
class A:
|
class A:
|
||||||
def a(self): ...
|
def a(self): ...
|
||||||
aa: int = 1
|
aa: int = 1
|
||||||
|
|
@ -116,6 +118,26 @@ def _(x: object, y: SomeTypedDict, z: Callable[[int, str], bool]):
|
||||||
|
|
||||||
# revealed: <super: <class 'object'>, dict[Literal["x", "y"], int | bytes]>
|
# revealed: <super: <class 'object'>, dict[Literal["x", "y"], int | bytes]>
|
||||||
reveal_type(super(object, y))
|
reveal_type(super(object, y))
|
||||||
|
|
||||||
|
# The first argument to `super()` must be an actual class object;
|
||||||
|
# instances of `GenericAlias` are not accepted at runtime:
|
||||||
|
#
|
||||||
|
# error: [invalid-super-argument]
|
||||||
|
# revealed: Unknown
|
||||||
|
reveal_type(super(list[int], []))
|
||||||
|
```
|
||||||
|
|
||||||
|
`super(pivot_class, owner)` can be called from inside methods, just like single-argument `super()`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Super:
|
||||||
|
def method(self) -> int:
|
||||||
|
return 42
|
||||||
|
|
||||||
|
class Sub(Super):
|
||||||
|
def method(self: Sub) -> int:
|
||||||
|
# revealed: <super: <class 'Sub'>, Sub>
|
||||||
|
return reveal_type(super(self.__class__, self)).method()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Implicit Super Object
|
### Implicit Super Object
|
||||||
|
|
|
||||||
|
|
@ -12,104 +12,121 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/class/super.md
|
||||||
## mdtest_snippet.py
|
## mdtest_snippet.py
|
||||||
|
|
||||||
```
|
```
|
||||||
1 | class A:
|
1 | from __future__ import annotations
|
||||||
2 | def a(self): ...
|
2 |
|
||||||
3 | aa: int = 1
|
3 | class A:
|
||||||
4 |
|
4 | def a(self): ...
|
||||||
5 | class B(A):
|
5 | aa: int = 1
|
||||||
6 | def b(self): ...
|
6 |
|
||||||
7 | bb: int = 2
|
7 | class B(A):
|
||||||
8 |
|
8 | def b(self): ...
|
||||||
9 | class C(B):
|
9 | bb: int = 2
|
||||||
10 | def c(self): ...
|
10 |
|
||||||
11 | cc: int = 3
|
11 | class C(B):
|
||||||
12 |
|
12 | def c(self): ...
|
||||||
13 | reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'B'>, <class 'A'>, <class 'object'>]
|
13 | cc: int = 3
|
||||||
14 |
|
14 |
|
||||||
15 | super(C, C()).a
|
15 | reveal_type(C.__mro__) # revealed: tuple[<class 'C'>, <class 'B'>, <class 'A'>, <class 'object'>]
|
||||||
16 | super(C, C()).b
|
16 |
|
||||||
17 | super(C, C()).c # error: [unresolved-attribute]
|
17 | super(C, C()).a
|
||||||
18 |
|
18 | super(C, C()).b
|
||||||
19 | super(B, C()).a
|
19 | super(C, C()).c # error: [unresolved-attribute]
|
||||||
20 | super(B, C()).b # error: [unresolved-attribute]
|
20 |
|
||||||
21 | super(B, C()).c # error: [unresolved-attribute]
|
21 | super(B, C()).a
|
||||||
22 |
|
22 | super(B, C()).b # error: [unresolved-attribute]
|
||||||
23 | super(A, C()).a # error: [unresolved-attribute]
|
23 | super(B, C()).c # error: [unresolved-attribute]
|
||||||
24 | super(A, C()).b # error: [unresolved-attribute]
|
24 |
|
||||||
25 | super(A, C()).c # error: [unresolved-attribute]
|
25 | super(A, C()).a # error: [unresolved-attribute]
|
||||||
26 |
|
26 | super(A, C()).b # error: [unresolved-attribute]
|
||||||
27 | reveal_type(super(C, C()).a) # revealed: bound method C.a() -> Unknown
|
27 | super(A, C()).c # error: [unresolved-attribute]
|
||||||
28 | reveal_type(super(C, C()).b) # revealed: bound method C.b() -> Unknown
|
28 |
|
||||||
29 | reveal_type(super(C, C()).aa) # revealed: int
|
29 | reveal_type(super(C, C()).a) # revealed: bound method C.a() -> Unknown
|
||||||
30 | reveal_type(super(C, C()).bb) # revealed: int
|
30 | reveal_type(super(C, C()).b) # revealed: bound method C.b() -> Unknown
|
||||||
31 | import types
|
31 | reveal_type(super(C, C()).aa) # revealed: int
|
||||||
32 | from typing_extensions import Callable, TypeIs, Literal, TypedDict
|
32 | reveal_type(super(C, C()).bb) # revealed: int
|
||||||
33 |
|
33 | import types
|
||||||
34 | def f(): ...
|
34 | from typing_extensions import Callable, TypeIs, Literal, TypedDict
|
||||||
35 |
|
35 |
|
||||||
36 | class Foo[T]:
|
36 | def f(): ...
|
||||||
37 | def method(self): ...
|
37 |
|
||||||
38 | @property
|
38 | class Foo[T]:
|
||||||
39 | def some_property(self): ...
|
39 | def method(self): ...
|
||||||
40 |
|
40 | @property
|
||||||
41 | type Alias = int
|
41 | def some_property(self): ...
|
||||||
42 |
|
42 |
|
||||||
43 | class SomeTypedDict(TypedDict):
|
43 | type Alias = int
|
||||||
44 | x: int
|
44 |
|
||||||
45 | y: bytes
|
45 | class SomeTypedDict(TypedDict):
|
||||||
46 |
|
46 | x: int
|
||||||
47 | # revealed: <super: <class 'object'>, FunctionType>
|
47 | y: bytes
|
||||||
48 | reveal_type(super(object, f))
|
48 |
|
||||||
49 | # revealed: <super: <class 'object'>, WrapperDescriptorType>
|
49 | # revealed: <super: <class 'object'>, FunctionType>
|
||||||
50 | reveal_type(super(object, types.FunctionType.__get__))
|
50 | reveal_type(super(object, f))
|
||||||
51 | # revealed: <super: <class 'object'>, GenericAlias>
|
51 | # revealed: <super: <class 'object'>, WrapperDescriptorType>
|
||||||
52 | reveal_type(super(object, Foo[int]))
|
52 | reveal_type(super(object, types.FunctionType.__get__))
|
||||||
53 | # revealed: <super: <class 'object'>, _SpecialForm>
|
53 | # revealed: <super: <class 'object'>, GenericAlias>
|
||||||
54 | reveal_type(super(object, Literal))
|
54 | reveal_type(super(object, Foo[int]))
|
||||||
55 | # revealed: <super: <class 'object'>, TypeAliasType>
|
55 | # revealed: <super: <class 'object'>, _SpecialForm>
|
||||||
56 | reveal_type(super(object, Alias))
|
56 | reveal_type(super(object, Literal))
|
||||||
57 | # revealed: <super: <class 'object'>, MethodType>
|
57 | # revealed: <super: <class 'object'>, TypeAliasType>
|
||||||
58 | reveal_type(super(object, Foo().method))
|
58 | reveal_type(super(object, Alias))
|
||||||
59 | # revealed: <super: <class 'object'>, property>
|
59 | # revealed: <super: <class 'object'>, MethodType>
|
||||||
60 | reveal_type(super(object, Foo.some_property))
|
60 | reveal_type(super(object, Foo().method))
|
||||||
61 |
|
61 | # revealed: <super: <class 'object'>, property>
|
||||||
62 | def g(x: object) -> TypeIs[list[object]]:
|
62 | reveal_type(super(object, Foo.some_property))
|
||||||
63 | return isinstance(x, list)
|
63 |
|
||||||
64 |
|
64 | def g(x: object) -> TypeIs[list[object]]:
|
||||||
65 | def _(x: object, y: SomeTypedDict, z: Callable[[int, str], bool]):
|
65 | return isinstance(x, list)
|
||||||
66 | if hasattr(x, "bar"):
|
66 |
|
||||||
67 | # revealed: <Protocol with members 'bar'>
|
67 | def _(x: object, y: SomeTypedDict, z: Callable[[int, str], bool]):
|
||||||
68 | reveal_type(x)
|
68 | if hasattr(x, "bar"):
|
||||||
69 | # error: [invalid-super-argument]
|
69 | # revealed: <Protocol with members 'bar'>
|
||||||
70 | # revealed: Unknown
|
70 | reveal_type(x)
|
||||||
71 | reveal_type(super(object, x))
|
71 | # error: [invalid-super-argument]
|
||||||
72 |
|
72 | # revealed: Unknown
|
||||||
73 | # error: [invalid-super-argument]
|
73 | reveal_type(super(object, x))
|
||||||
74 | # revealed: Unknown
|
74 |
|
||||||
75 | reveal_type(super(object, z))
|
75 | # error: [invalid-super-argument]
|
||||||
76 |
|
76 | # revealed: Unknown
|
||||||
77 | is_list = g(x)
|
77 | reveal_type(super(object, z))
|
||||||
78 | # revealed: TypeIs[list[object] @ x]
|
78 |
|
||||||
79 | reveal_type(is_list)
|
79 | is_list = g(x)
|
||||||
80 | # revealed: <super: <class 'object'>, bool>
|
80 | # revealed: TypeIs[list[object] @ x]
|
||||||
81 | reveal_type(super(object, is_list))
|
81 | reveal_type(is_list)
|
||||||
82 |
|
82 | # revealed: <super: <class 'object'>, bool>
|
||||||
83 | # revealed: <super: <class 'object'>, dict[Literal["x", "y"], int | bytes]>
|
83 | reveal_type(super(object, is_list))
|
||||||
84 | reveal_type(super(object, y))
|
84 |
|
||||||
|
85 | # revealed: <super: <class 'object'>, dict[Literal["x", "y"], int | bytes]>
|
||||||
|
86 | reveal_type(super(object, y))
|
||||||
|
87 |
|
||||||
|
88 | # The first argument to `super()` must be an actual class object;
|
||||||
|
89 | # instances of `GenericAlias` are not accepted at runtime:
|
||||||
|
90 | #
|
||||||
|
91 | # error: [invalid-super-argument]
|
||||||
|
92 | # revealed: Unknown
|
||||||
|
93 | reveal_type(super(list[int], []))
|
||||||
|
94 | class Super:
|
||||||
|
95 | def method(self) -> int:
|
||||||
|
96 | return 42
|
||||||
|
97 |
|
||||||
|
98 | class Sub(Super):
|
||||||
|
99 | def method(self: Sub) -> int:
|
||||||
|
100 | # revealed: <super: <class 'Sub'>, Sub>
|
||||||
|
101 | return reveal_type(super(self.__class__, self)).method()
|
||||||
```
|
```
|
||||||
|
|
||||||
# Diagnostics
|
# Diagnostics
|
||||||
|
|
||||||
```
|
```
|
||||||
error[unresolved-attribute]: Type `<super: <class 'C'>, C>` has no attribute `c`
|
error[unresolved-attribute]: Type `<super: <class 'C'>, C>` has no attribute `c`
|
||||||
--> src/mdtest_snippet.py:17:1
|
--> src/mdtest_snippet.py:19:1
|
||||||
|
|
|
|
||||||
15 | super(C, C()).a
|
17 | super(C, C()).a
|
||||||
16 | super(C, C()).b
|
18 | super(C, C()).b
|
||||||
17 | super(C, C()).c # error: [unresolved-attribute]
|
19 | super(C, C()).c # error: [unresolved-attribute]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
18 |
|
20 |
|
||||||
19 | super(B, C()).a
|
21 | super(B, C()).a
|
||||||
|
|
|
|
||||||
info: rule `unresolved-attribute` is enabled by default
|
info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
|
|
@ -117,12 +134,12 @@ info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
error[unresolved-attribute]: Type `<super: <class 'B'>, C>` has no attribute `b`
|
error[unresolved-attribute]: Type `<super: <class 'B'>, C>` has no attribute `b`
|
||||||
--> src/mdtest_snippet.py:20:1
|
--> src/mdtest_snippet.py:22:1
|
||||||
|
|
|
|
||||||
19 | super(B, C()).a
|
21 | super(B, C()).a
|
||||||
20 | super(B, C()).b # error: [unresolved-attribute]
|
22 | super(B, C()).b # error: [unresolved-attribute]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
21 | super(B, C()).c # error: [unresolved-attribute]
|
23 | super(B, C()).c # error: [unresolved-attribute]
|
||||||
|
|
|
|
||||||
info: rule `unresolved-attribute` is enabled by default
|
info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
|
|
@ -130,14 +147,14 @@ info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
error[unresolved-attribute]: Type `<super: <class 'B'>, C>` has no attribute `c`
|
error[unresolved-attribute]: Type `<super: <class 'B'>, C>` has no attribute `c`
|
||||||
--> src/mdtest_snippet.py:21:1
|
--> src/mdtest_snippet.py:23:1
|
||||||
|
|
|
|
||||||
19 | super(B, C()).a
|
21 | super(B, C()).a
|
||||||
20 | super(B, C()).b # error: [unresolved-attribute]
|
22 | super(B, C()).b # error: [unresolved-attribute]
|
||||||
21 | super(B, C()).c # error: [unresolved-attribute]
|
23 | super(B, C()).c # error: [unresolved-attribute]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
22 |
|
24 |
|
||||||
23 | super(A, C()).a # error: [unresolved-attribute]
|
25 | super(A, C()).a # error: [unresolved-attribute]
|
||||||
|
|
|
|
||||||
info: rule `unresolved-attribute` is enabled by default
|
info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
|
|
@ -145,14 +162,14 @@ info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
error[unresolved-attribute]: Type `<super: <class 'A'>, C>` has no attribute `a`
|
error[unresolved-attribute]: Type `<super: <class 'A'>, C>` has no attribute `a`
|
||||||
--> src/mdtest_snippet.py:23:1
|
--> src/mdtest_snippet.py:25:1
|
||||||
|
|
|
|
||||||
21 | super(B, C()).c # error: [unresolved-attribute]
|
23 | super(B, C()).c # error: [unresolved-attribute]
|
||||||
22 |
|
24 |
|
||||||
23 | super(A, C()).a # error: [unresolved-attribute]
|
25 | super(A, C()).a # error: [unresolved-attribute]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
24 | super(A, C()).b # error: [unresolved-attribute]
|
26 | super(A, C()).b # error: [unresolved-attribute]
|
||||||
25 | super(A, C()).c # error: [unresolved-attribute]
|
27 | super(A, C()).c # error: [unresolved-attribute]
|
||||||
|
|
|
|
||||||
info: rule `unresolved-attribute` is enabled by default
|
info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
|
|
@ -160,12 +177,12 @@ info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
error[unresolved-attribute]: Type `<super: <class 'A'>, C>` has no attribute `b`
|
error[unresolved-attribute]: Type `<super: <class 'A'>, C>` has no attribute `b`
|
||||||
--> src/mdtest_snippet.py:24:1
|
--> src/mdtest_snippet.py:26:1
|
||||||
|
|
|
|
||||||
23 | super(A, C()).a # error: [unresolved-attribute]
|
25 | super(A, C()).a # error: [unresolved-attribute]
|
||||||
24 | super(A, C()).b # error: [unresolved-attribute]
|
26 | super(A, C()).b # error: [unresolved-attribute]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
25 | super(A, C()).c # error: [unresolved-attribute]
|
27 | super(A, C()).c # error: [unresolved-attribute]
|
||||||
|
|
|
|
||||||
info: rule `unresolved-attribute` is enabled by default
|
info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
|
|
@ -173,14 +190,14 @@ info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
error[unresolved-attribute]: Type `<super: <class 'A'>, C>` has no attribute `c`
|
error[unresolved-attribute]: Type `<super: <class 'A'>, C>` has no attribute `c`
|
||||||
--> src/mdtest_snippet.py:25:1
|
--> src/mdtest_snippet.py:27:1
|
||||||
|
|
|
|
||||||
23 | super(A, C()).a # error: [unresolved-attribute]
|
25 | super(A, C()).a # error: [unresolved-attribute]
|
||||||
24 | super(A, C()).b # error: [unresolved-attribute]
|
26 | super(A, C()).b # error: [unresolved-attribute]
|
||||||
25 | super(A, C()).c # error: [unresolved-attribute]
|
27 | super(A, C()).c # error: [unresolved-attribute]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
26 |
|
28 |
|
||||||
27 | reveal_type(super(C, C()).a) # revealed: bound method C.a() -> Unknown
|
29 | reveal_type(super(C, C()).a) # revealed: bound method C.a() -> Unknown
|
||||||
|
|
|
|
||||||
info: rule `unresolved-attribute` is enabled by default
|
info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
|
|
@ -188,14 +205,14 @@ info: rule `unresolved-attribute` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
error[invalid-super-argument]: `<Protocol with members 'bar'>` is an abstract/structural type in `super(<class 'object'>, <Protocol with members 'bar'>)` call
|
error[invalid-super-argument]: `<Protocol with members 'bar'>` is an abstract/structural type in `super(<class 'object'>, <Protocol with members 'bar'>)` call
|
||||||
--> src/mdtest_snippet.py:71:21
|
--> src/mdtest_snippet.py:73:21
|
||||||
|
|
|
|
||||||
69 | # error: [invalid-super-argument]
|
71 | # error: [invalid-super-argument]
|
||||||
70 | # revealed: Unknown
|
72 | # revealed: Unknown
|
||||||
71 | reveal_type(super(object, x))
|
73 | reveal_type(super(object, x))
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
72 |
|
74 |
|
||||||
73 | # error: [invalid-super-argument]
|
75 | # error: [invalid-super-argument]
|
||||||
|
|
|
|
||||||
info: rule `invalid-super-argument` is enabled by default
|
info: rule `invalid-super-argument` is enabled by default
|
||||||
|
|
||||||
|
|
@ -203,14 +220,29 @@ info: rule `invalid-super-argument` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
error[invalid-super-argument]: `(int, str, /) -> bool` is an abstract/structural type in `super(<class 'object'>, (int, str, /) -> bool)` call
|
error[invalid-super-argument]: `(int, str, /) -> bool` is an abstract/structural type in `super(<class 'object'>, (int, str, /) -> bool)` call
|
||||||
--> src/mdtest_snippet.py:75:17
|
--> src/mdtest_snippet.py:77:17
|
||||||
|
|
|
|
||||||
73 | # error: [invalid-super-argument]
|
75 | # error: [invalid-super-argument]
|
||||||
74 | # revealed: Unknown
|
76 | # revealed: Unknown
|
||||||
75 | reveal_type(super(object, z))
|
77 | reveal_type(super(object, z))
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
76 |
|
78 |
|
||||||
77 | is_list = g(x)
|
79 | is_list = g(x)
|
||||||
|
|
|
||||||
|
info: rule `invalid-super-argument` is enabled by default
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
error[invalid-super-argument]: `types.GenericAlias` instance `list[int]` is not a valid class
|
||||||
|
--> src/mdtest_snippet.py:93:13
|
||||||
|
|
|
||||||
|
91 | # error: [invalid-super-argument]
|
||||||
|
92 | # revealed: Unknown
|
||||||
|
93 | reveal_type(super(list[int], []))
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
94 | class Super:
|
||||||
|
95 | def method(self) -> int:
|
||||||
|
|
|
|
||||||
info: rule `invalid-super-argument` is enabled by default
|
info: rule `invalid-super-argument` is enabled by default
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ error[invalid-super-argument]: `S@method7` is not an instance or subclass of `<c
|
||||||
|
|
|
|
||||||
info: Type variable `S` has `object` as its implicit upper bound
|
info: Type variable `S` has `object` as its implicit upper bound
|
||||||
info: `object` is not an instance or subclass of `<class 'Foo'>`
|
info: `object` is not an instance or subclass of `<class 'Foo'>`
|
||||||
|
help: Consider adding an upper bound to type variable `S`
|
||||||
info: rule `invalid-super-argument` is enabled by default
|
info: rule `invalid-super-argument` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -7790,6 +7790,12 @@ pub enum TypeVarKind {
|
||||||
TypingSelf,
|
TypingSelf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypeVarKind {
|
||||||
|
const fn is_self(self) -> bool {
|
||||||
|
matches!(self, Self::TypingSelf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The identity of a type variable.
|
/// The identity of a type variable.
|
||||||
///
|
///
|
||||||
/// This represents the core identity of a typevar, independent of its bounds or constraints. Two
|
/// This represents the core identity of a typevar, independent of its bounds or constraints. Two
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use ruff_db::diagnostic::Diagnostic;
|
||||||
use ruff_python_ast::AnyNodeRef;
|
use ruff_python_ast::AnyNodeRef;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Db,
|
Db, DisplaySettings,
|
||||||
place::{Place, PlaceAndQualifiers},
|
place::{Place, PlaceAndQualifiers},
|
||||||
types::{
|
types::{
|
||||||
ClassBase, ClassType, DynamicType, IntersectionBuilder, KnownClass, MemberLookupPolicy,
|
ClassBase, ClassType, DynamicType, IntersectionBuilder, KnownClass, MemberLookupPolicy,
|
||||||
|
|
@ -75,10 +75,16 @@ impl<'db> BoundSuperError<'db> {
|
||||||
}
|
}
|
||||||
BoundSuperError::InvalidPivotClassType { pivot_class } => {
|
BoundSuperError::InvalidPivotClassType { pivot_class } => {
|
||||||
if let Some(builder) = context.report_lint(&INVALID_SUPER_ARGUMENT, node) {
|
if let Some(builder) = context.report_lint(&INVALID_SUPER_ARGUMENT, node) {
|
||||||
builder.into_diagnostic(format_args!(
|
match pivot_class {
|
||||||
"`{pivot_class}` is not a valid class",
|
Type::GenericAlias(alias) => builder.into_diagnostic(format_args!(
|
||||||
pivot_class = pivot_class.display(context.db()),
|
"`types.GenericAlias` instance `{}` is not a valid class",
|
||||||
));
|
alias.display_with(context.db(), DisplaySettings::default()),
|
||||||
|
)),
|
||||||
|
_ => builder.into_diagnostic(format_args!(
|
||||||
|
"`{pivot_class}` is not a valid class",
|
||||||
|
pivot_class = pivot_class.display(context.db()),
|
||||||
|
)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundSuperError::FailingConditionCheck {
|
BoundSuperError::FailingConditionCheck {
|
||||||
|
|
@ -102,6 +108,14 @@ impl<'db> BoundSuperError<'db> {
|
||||||
bound_or_constraints_union.display(context.db()),
|
bound_or_constraints_union.display(context.db()),
|
||||||
pivot_class = pivot_class.display(context.db()),
|
pivot_class = pivot_class.display(context.db()),
|
||||||
));
|
));
|
||||||
|
if typevar_context.bound_or_constraints(context.db()).is_none()
|
||||||
|
&& !typevar_context.kind(context.db()).is_self()
|
||||||
|
{
|
||||||
|
diagnostic.help(format_args!(
|
||||||
|
"Consider adding an upper bound to type variable `{}`",
|
||||||
|
typevar_context.name(context.db())
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -412,15 +426,10 @@ impl<'db> BoundSuperType<'db> {
|
||||||
// but are valid as pivot classes, e.g. unsubscripted `typing.Generic`
|
// but are valid as pivot classes, e.g. unsubscripted `typing.Generic`
|
||||||
let pivot_class = match pivot_class_type {
|
let pivot_class = match pivot_class_type {
|
||||||
Type::ClassLiteral(class) => ClassBase::Class(ClassType::NonGeneric(class)),
|
Type::ClassLiteral(class) => ClassBase::Class(ClassType::NonGeneric(class)),
|
||||||
Type::GenericAlias(class) => ClassBase::Class(ClassType::Generic(class)),
|
Type::SubclassOf(subclass_of) => match subclass_of.subclass_of() {
|
||||||
Type::SubclassOf(subclass_of) if subclass_of.subclass_of().is_dynamic() => {
|
SubclassOfInner::Class(class) => ClassBase::Class(class),
|
||||||
ClassBase::Dynamic(
|
SubclassOfInner::Dynamic(dynamic) => ClassBase::Dynamic(dynamic),
|
||||||
subclass_of
|
},
|
||||||
.subclass_of()
|
|
||||||
.into_dynamic()
|
|
||||||
.expect("Checked in branch arm"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Type::SpecialForm(SpecialFormType::Protocol) => ClassBase::Protocol,
|
Type::SpecialForm(SpecialFormType::Protocol) => ClassBase::Protocol,
|
||||||
Type::SpecialForm(SpecialFormType::Generic) => ClassBase::Generic,
|
Type::SpecialForm(SpecialFormType::Generic) => ClassBase::Generic,
|
||||||
Type::SpecialForm(SpecialFormType::TypedDict) => ClassBase::TypedDict,
|
Type::SpecialForm(SpecialFormType::TypedDict) => ClassBase::TypedDict,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue