Skip to content

Commit ad3d451

Browse files
committed
many diagnostics improvements
1 parent 2a8e985 commit ad3d451

7 files changed

+350
-230
lines changed

crates/ty_python_semantic/resources/mdtest/slots.md renamed to crates/ty_python_semantic/resources/mdtest/instance_layout_conflict.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# `__slots__`
1+
# Tests for ty's `instance-layout-conflict` error code
22

3-
## Not specified and empty
3+
## `__slots__`: not specified or empty
44

55
```py
66
class A: ...
@@ -17,7 +17,7 @@ class BC(B, C): ... # fine
1717
class ABC(A, B, C): ... # fine
1818
```
1919

20-
## Incompatible tuples
20+
## `__slots__`: incompatible tuples
2121

2222
<!-- snapshot-diagnostics -->
2323

@@ -34,7 +34,7 @@ class C( # error: [instance-layout-conflict]
3434
): ...
3535
```
3636

37-
## Same value
37+
## `__slots__` are the same value
3838

3939
```py
4040
class A:
@@ -49,7 +49,7 @@ class C( # error: [instance-layout-conflict]
4949
): ...
5050
```
5151

52-
## Strings
52+
## `__slots__` is a string
5353

5454
```py
5555
class A:
@@ -64,7 +64,7 @@ class AB( # error: [instance-layout-conflict]
6464
): ...
6565
```
6666

67-
## Invalid
67+
## Invalid `__slots__` definitions
6868

6969
TODO: Emit diagnostics
7070

@@ -85,7 +85,7 @@ class NonIdentifier3:
8585
__slots__ = (e for e in ("lorem", "42"))
8686
```
8787

88-
## Inheritance
88+
## Inherited `__slots__`
8989

9090
```py
9191
class A:
@@ -103,7 +103,7 @@ class E( # error: [instance-layout-conflict]
103103
): ...
104104
```
105105

106-
## Single solid base
106+
## A single "solid base"
107107

108108
```py
109109
class A:
@@ -115,7 +115,7 @@ class D(B, A): ... # fine
115115
class E(B, C, A): ... # fine
116116
```
117117

118-
## Post-hoc modifications
118+
## Post-hoc modifications to `__slots__`
119119

120120
```py
121121
class A:
@@ -178,6 +178,8 @@ class E( # error: [instance-layout-conflict]
178178
str
179179
): ...
180180

181+
class F(int, str, bytes, bytearray): ... # error: [instance-layout-conflict]
182+
181183
# fmt: on
182184
```
183185

@@ -188,7 +190,7 @@ We avoid emitting an `instance-layout-conflict` diagnostic for this class defini
188190
class Foo(range, str): ... # error: [subclass-of-final-class]
189191
```
190192

191-
## Multiple solid bases where one is a subclass of the other
193+
## Multiple "solid bases" where one is a subclass of the other
192194

193195
A class is permitted to multiple-inherit from multiple solid bases if one is a subclass of the
194196
other:
@@ -219,7 +221,7 @@ class FF(CC, DD): ... # fine
219221

220222
## False negatives
221223

222-
### Possibly unbound
224+
### Possibly unbound `__slots__`
223225

224226
```py
225227
def _(flag: bool):
@@ -234,7 +236,7 @@ def _(flag: bool):
234236
class C(A, B): ...
235237
```
236238

237-
### Bound but with different types
239+
### Bound `__slots__` but with different types
238240

239241
```py
240242
def _(flag: bool):
@@ -251,7 +253,7 @@ def _(flag: bool):
251253
class C(A, B): ...
252254
```
253255

254-
### Non-tuples
256+
### Non-tuple `__slots__` definitions
255257

256258
```py
257259
class A:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
source: crates/ty_test/src/lib.rs
3+
expression: snapshot
4+
---
5+
---
6+
mdtest name: instance_layout_conflict.md - Tests for ty's `instance-layout-conflict` error code - Built-ins with implicit layouts
7+
mdtest path: crates/ty_python_semantic/resources/mdtest/instance_layout_conflict.md
8+
---
9+
10+
# Python source files
11+
12+
## mdtest_snippet.py
13+
14+
```
15+
1 | # fmt: off
16+
2 |
17+
3 | class A( # error: [instance-layout-conflict]
18+
4 | int,
19+
5 | str
20+
6 | ): ...
21+
7 |
22+
8 | class B:
23+
9 | __slots__ = ("b",)
24+
10 |
25+
11 | class C( # error: [instance-layout-conflict]
26+
12 | int,
27+
13 | B,
28+
14 | ): ...
29+
15 | class D(int): ...
30+
16 |
31+
17 | class E( # error: [instance-layout-conflict]
32+
18 | D,
33+
19 | str
34+
20 | ): ...
35+
21 |
36+
22 | class F(int, str, bytes, bytearray): ... # error: [instance-layout-conflict]
37+
23 |
38+
24 | # fmt: on
39+
25 | class Foo(range, str): ... # error: [subclass-of-final-class]
40+
```
41+
42+
# Diagnostics
43+
44+
```
45+
error[instance-layout-conflict]: Class will raise `TypeError` at runtime due to incompatible bases
46+
--> src/mdtest_snippet.py:3:7
47+
|
48+
1 | # fmt: off
49+
2 |
50+
3 | class A( # error: [instance-layout-conflict]
51+
| _______^
52+
4 | | int,
53+
5 | | str
54+
6 | | ): ...
55+
| |_^ Bases `int` and `str` cannot be combined in multiple inheritance
56+
7 |
57+
8 | class B:
58+
|
59+
info: Two classes cannot coexist in a class's MRO if they create objects with incompatible memory layouts when they are instantiated
60+
--> src/mdtest_snippet.py:4:5
61+
|
62+
3 | class A( # error: [instance-layout-conflict]
63+
4 | int,
64+
| --- `int` instances have a distinct memory layout because of the way `int` is implemented in a C extension
65+
5 | str
66+
| --- `str` instances have a distinct memory layout because of the way `str` is implemented in a C extension
67+
6 | ): ...
68+
|
69+
info: rule `instance-layout-conflict` is enabled by default
70+
71+
```
72+
73+
```
74+
error[instance-layout-conflict]: Class will raise `TypeError` at runtime due to incompatible bases
75+
--> src/mdtest_snippet.py:11:7
76+
|
77+
9 | __slots__ = ("b",)
78+
10 |
79+
11 | class C( # error: [instance-layout-conflict]
80+
| _______^
81+
12 | | int,
82+
13 | | B,
83+
14 | | ): ...
84+
| |_^ Bases `int` and `B` cannot be combined in multiple inheritance
85+
15 | class D(int): ...
86+
|
87+
info: Two classes cannot coexist in a class's MRO if they create objects with incompatible memory layouts when they are instantiated
88+
--> src/mdtest_snippet.py:12:5
89+
|
90+
11 | class C( # error: [instance-layout-conflict]
91+
12 | int,
92+
| --- `int` instances have a distinct memory layout because of the way `int` is implemented in a C extension
93+
13 | B,
94+
| - `B` instances have a distinct memory layout because `B` defines non-empty `__slots__`
95+
14 | ): ...
96+
15 | class D(int): ...
97+
|
98+
info: rule `instance-layout-conflict` is enabled by default
99+
100+
```
101+
102+
```
103+
error[instance-layout-conflict]: Class will raise `TypeError` at runtime due to incompatible bases
104+
--> src/mdtest_snippet.py:17:7
105+
|
106+
15 | class D(int): ...
107+
16 |
108+
17 | class E( # error: [instance-layout-conflict]
109+
| _______^
110+
18 | | D,
111+
19 | | str
112+
20 | | ): ...
113+
| |_^ Bases `D` and `str` cannot be combined in multiple inheritance
114+
21 |
115+
22 | class F(int, str, bytes, bytearray): ... # error: [instance-layout-conflict]
116+
|
117+
info: Two classes cannot coexist in a class's MRO if they create objects with incompatible memory layouts when they are instantiated
118+
--> src/mdtest_snippet.py:18:5
119+
|
120+
17 | class E( # error: [instance-layout-conflict]
121+
18 | D,
122+
| -
123+
| |
124+
| `D` instances have a distinct memory layout because `D` inherits from `int`
125+
| `int` instances have a distinct memory layout because of the way `int` is implemented in a C extension
126+
19 | str
127+
| --- `str` instances have a distinct memory layout because of the way `str` is implemented in a C extension
128+
20 | ): ...
129+
|
130+
info: rule `instance-layout-conflict` is enabled by default
131+
132+
```
133+
134+
```
135+
error[instance-layout-conflict]: Class will raise `TypeError` at runtime due to incompatible bases
136+
--> src/mdtest_snippet.py:22:7
137+
|
138+
20 | ): ...
139+
21 |
140+
22 | class F(int, str, bytes, bytearray): ... # error: [instance-layout-conflict]
141+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Bases `int`, `str`, `bytes` and `bytearray` cannot be combined in multiple inheritance
142+
23 |
143+
24 | # fmt: on
144+
|
145+
info: Two classes cannot coexist in a class's MRO if they create objects with incompatible memory layouts when they are instantiated
146+
--> src/mdtest_snippet.py:22:9
147+
|
148+
20 | ): ...
149+
21 |
150+
22 | class F(int, str, bytes, bytearray): ... # error: [instance-layout-conflict]
151+
| --- --- ----- --------- `bytearray` instances have a distinct memory layout because of the way `bytearray` is implemented in a C extension
152+
| | | |
153+
| | | `bytes` instances have a distinct memory layout because of the way `bytes` is implemented in a C extension
154+
| | `str` instances have a distinct memory layout because of the way `str` is implemented in a C extension
155+
| `int` instances have a distinct memory layout because of the way `int` is implemented in a C extension
156+
23 |
157+
24 | # fmt: on
158+
|
159+
info: rule `instance-layout-conflict` is enabled by default
160+
161+
```
162+
163+
```
164+
error[subclass-of-final-class]: Class `Foo` cannot inherit from final class `range`
165+
--> src/mdtest_snippet.py:25:11
166+
|
167+
24 | # fmt: on
168+
25 | class Foo(range, str): ... # error: [subclass-of-final-class]
169+
| ^^^^^
170+
|
171+
info: rule `subclass-of-final-class` is enabled by default
172+
173+
```

crates/ty_python_semantic/resources/mdtest/snapshots/slots.md_-_`__slots__`_-_Incompatible_tuples_(4f3cb4818a064181).snap renamed to crates/ty_python_semantic/resources/mdtest/snapshots/instance_layout_conf…_-_Tests_for_ty's_`inst…_-_`__slots__`___incompa…_(98b54233987eb654).snap

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ source: crates/ty_test/src/lib.rs
33
expression: snapshot
44
---
55
---
6-
mdtest name: slots.md - `__slots__` - Incompatible tuples
7-
mdtest path: crates/ty_python_semantic/resources/mdtest/slots.md
6+
mdtest name: instance_layout_conflict.md - Tests for ty's `instance-layout-conflict` error code - `__slots__`: incompatible tuples
7+
mdtest path: crates/ty_python_semantic/resources/mdtest/instance_layout_conflict.md
88
---
99

1010
# Python source files
@@ -27,7 +27,7 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/slots.md
2727
# Diagnostics
2828

2929
```
30-
error[instance-layout-conflict]: Class will raise `TypeError` at runtime due to its bases
30+
error[instance-layout-conflict]: Class will raise `TypeError` at runtime due to incompatible bases
3131
--> src/mdtest_snippet.py:7:7
3232
|
3333
5 | __slots__ = ("c", "d")
@@ -37,16 +37,16 @@ error[instance-layout-conflict]: Class will raise `TypeError` at runtime due to
3737
8 | | A,
3838
9 | | B,
3939
10 | | ): ...
40-
| |_^ Bases `A`, `B` cannot be combined in multiple inheritance
40+
| |_^ Bases `A` and `B` cannot be combined in multiple inheritance
4141
|
42-
info: Two "solid bases" cannot coexist in a class's MRO unless one inherits from the other
42+
info: Two classes cannot coexist in a class's MRO if they create objects with incompatible memory layouts when they are instantiated
4343
--> src/mdtest_snippet.py:8:5
4444
|
4545
7 | class C( # error: [instance-layout-conflict]
4646
8 | A,
47-
| - `A` is a solid base because it defines non-empty `__slots__`
47+
| - `A` instances have a distinct memory layout because `A` defines non-empty `__slots__`
4848
9 | B,
49-
| - `B` is a solid base because it defines non-empty `__slots__`
49+
| - `B` instances have a distinct memory layout because `B` defines non-empty `__slots__`
5050
10 | ): ...
5151
|
5252
info: rule `instance-layout-conflict` is enabled by default

0 commit comments

Comments
 (0)