red_knot_python_semantic: migrate types to new diagnostics

This commit is contained in:
Andrew Gallant 2025-04-22 10:50:00 -04:00 committed by Andrew Gallant
parent c12640fea8
commit 17f799424a
25 changed files with 144 additions and 151 deletions

View file

@ -28,12 +28,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable` is not iterable because it has no `__iter__` method and its `__getitem__` method has an incorrect signature for the old-style iteration protocol (expected a signature at least as permissive as `def __getitem__(self, key: int): ...`)
--> /src/mdtest_snippet.py:10:10 --> /src/mdtest_snippet.py:10:10
| |
9 | # error: [not-iterable] 9 | # error: [not-iterable]
10 | for x in Iterable(): 10 | for x in Iterable():
| ^^^^^^^^^^ Object of type `Iterable` is not iterable because it has no `__iter__` method and its `__getitem__` method has an incorrect signature for the old-style iteration protocol (expected a signature at least as permissive as `def __getitem__(self, key: int): ...`) | ^^^^^^^^^^
11 | reveal_type(x) # revealed: int 11 | reveal_type(x) # revealed: int
| |

View file

@ -20,12 +20,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Literal[123]` is not iterable because it doesn't have an `__iter__` method or a `__getitem__` method
--> /src/mdtest_snippet.py:2:10 --> /src/mdtest_snippet.py:2:10
| |
1 | nonsense = 123 1 | nonsense = 123
2 | for x in nonsense: # error: [not-iterable] 2 | for x in nonsense: # error: [not-iterable]
| ^^^^^^^^ Object of type `Literal[123]` is not iterable because it doesn't have an `__iter__` method or a `__getitem__` method | ^^^^^^^^
3 | pass 3 | pass
| |

View file

@ -24,13 +24,13 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `NotIterable` is not iterable because its `__iter__` attribute has type `None`, which is not callable
--> /src/mdtest_snippet.py:6:10 --> /src/mdtest_snippet.py:6:10
| |
4 | __iter__: None = None 4 | __iter__: None = None
5 | 5 |
6 | for x in NotIterable(): # error: [not-iterable] 6 | for x in NotIterable(): # error: [not-iterable]
| ^^^^^^^^^^^^^ Object of type `NotIterable` is not iterable because its `__iter__` attribute has type `None`, which is not callable | ^^^^^^^^^^^^^
7 | pass 7 | pass
| |

View file

@ -25,12 +25,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Bad` is not iterable because it has no `__iter__` method and its `__getitem__` attribute has type `None`, which is not callable
--> /src/mdtest_snippet.py:7:10 --> /src/mdtest_snippet.py:7:10
| |
6 | # error: [not-iterable] 6 | # error: [not-iterable]
7 | for x in Bad(): 7 | for x in Bad():
| ^^^^^ Object of type `Bad` is not iterable because it has no `__iter__` method and its `__getitem__` attribute has type `None`, which is not callable | ^^^^^
8 | reveal_type(x) # revealed: Unknown 8 | reveal_type(x) # revealed: Unknown
| |

View file

@ -46,12 +46,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable1` may not be iterable because it has no `__iter__` method and its `__getitem__` attribute (with type `CustomCallable`) may not be callable
--> /src/mdtest_snippet.py:22:14 --> /src/mdtest_snippet.py:22:14
| |
21 | # error: [not-iterable] 21 | # error: [not-iterable]
22 | for x in Iterable1(): 22 | for x in Iterable1():
| ^^^^^^^^^^^ Object of type `Iterable1` may not be iterable because it has no `__iter__` method and its `__getitem__` attribute (with type `CustomCallable`) may not be callable | ^^^^^^^^^^^
23 | # TODO... `int` might be ideal here? 23 | # TODO... `int` might be ideal here?
24 | reveal_type(x) # revealed: int | Unknown 24 | reveal_type(x) # revealed: int | Unknown
| |
@ -73,12 +73,12 @@ info: revealed-type: Revealed type
``` ```
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable2` may not be iterable because it has no `__iter__` method and its `__getitem__` attribute (with type `(bound method Iterable2.__getitem__(key: int) -> int) | None`) may not be callable
--> /src/mdtest_snippet.py:27:14 --> /src/mdtest_snippet.py:27:14
| |
26 | # error: [not-iterable] 26 | # error: [not-iterable]
27 | for y in Iterable2(): 27 | for y in Iterable2():
| ^^^^^^^^^^^ Object of type `Iterable2` may not be iterable because it has no `__iter__` method and its `__getitem__` attribute (with type `(bound method Iterable2.__getitem__(key: int) -> int) | None`) may not be callable | ^^^^^^^^^^^
28 | # TODO... `int` might be ideal here? 28 | # TODO... `int` might be ideal here?
29 | reveal_type(y) # revealed: int | Unknown 29 | reveal_type(y) # revealed: int | Unknown
| |

View file

@ -43,12 +43,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable1` may not be iterable because it has no `__iter__` method and its `__getitem__` attribute (with type `(bound method Iterable1.__getitem__(item: int) -> str) | None`) may not be callable
--> /src/mdtest_snippet.py:20:14 --> /src/mdtest_snippet.py:20:14
| |
19 | # error: [not-iterable] 19 | # error: [not-iterable]
20 | for x in Iterable1(): 20 | for x in Iterable1():
| ^^^^^^^^^^^ Object of type `Iterable1` may not be iterable because it has no `__iter__` method and its `__getitem__` attribute (with type `(bound method Iterable1.__getitem__(item: int) -> str) | None`) may not be callable | ^^^^^^^^^^^
21 | # TODO: `str` might be better 21 | # TODO: `str` might be better
22 | reveal_type(x) # revealed: str | Unknown 22 | reveal_type(x) # revealed: str | Unknown
| |
@ -70,12 +70,12 @@ info: revealed-type: Revealed type
``` ```
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable2` may not be iterable because it has no `__iter__` method and its `__getitem__` method (with type `(bound method Iterable2.__getitem__(item: int) -> str) | (bound method Iterable2.__getitem__(item: str) -> int)`) may have an incorrect signature for the old-style iteration protocol (expected a signature at least as permissive as `def __getitem__(self, key: int): ...`)
--> /src/mdtest_snippet.py:25:14 --> /src/mdtest_snippet.py:25:14
| |
24 | # error: [not-iterable] 24 | # error: [not-iterable]
25 | for y in Iterable2(): 25 | for y in Iterable2():
| ^^^^^^^^^^^ Object of type `Iterable2` may not be iterable because it has no `__iter__` method and its `__getitem__` method (with type `(bound method Iterable2.__getitem__(item: int) -> str) | (bound method Iterable2.__getitem__(item: str) -> int)`) may have an incorrect signature for the old-style iteration protocol (expected a signature at least as permissive as `def __getitem__(self, key: int): ...`) | ^^^^^^^^^^^
26 | reveal_type(y) # revealed: str | int 26 | reveal_type(y) # revealed: str | int
| |

View file

@ -47,12 +47,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable1` may not be iterable because its `__iter__` method (with type `(bound method Iterable1.__iter__() -> Iterator) | (bound method Iterable1.__iter__(invalid_extra_arg) -> Iterator)`) may have an invalid signature (expected `def __iter__(self): ...`)
--> /src/mdtest_snippet.py:17:14 --> /src/mdtest_snippet.py:17:14
| |
16 | # error: [not-iterable] 16 | # error: [not-iterable]
17 | for x in Iterable1(): 17 | for x in Iterable1():
| ^^^^^^^^^^^ Object of type `Iterable1` may not be iterable because its `__iter__` method (with type `(bound method Iterable1.__iter__() -> Iterator) | (bound method Iterable1.__iter__(invalid_extra_arg) -> Iterator)`) may have an invalid signature (expected `def __iter__(self): ...`) | ^^^^^^^^^^^
18 | reveal_type(x) # revealed: int 18 | reveal_type(x) # revealed: int
| |
@ -73,12 +73,12 @@ info: revealed-type: Revealed type
``` ```
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable2` may not be iterable because its `__iter__` attribute (with type `(bound method Iterable2.__iter__() -> Iterator) | None`) may not be callable
--> /src/mdtest_snippet.py:28:14 --> /src/mdtest_snippet.py:28:14
| |
27 | # error: [not-iterable] 27 | # error: [not-iterable]
28 | for x in Iterable2(): 28 | for x in Iterable2():
| ^^^^^^^^^^^ Object of type `Iterable2` may not be iterable because its `__iter__` attribute (with type `(bound method Iterable2.__iter__() -> Iterator) | None`) may not be callable | ^^^^^^^^^^^
29 | # TODO: `int` would probably be better here: 29 | # TODO: `int` would probably be better here:
30 | reveal_type(x) # revealed: int | Unknown 30 | reveal_type(x) # revealed: int | Unknown
| |

View file

@ -51,12 +51,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable1` may not be iterable because its `__iter__` method returns an object of type `Iterator1`, which may have an invalid `__next__` method (expected `def __next__(self): ...`)
--> /src/mdtest_snippet.py:28:14 --> /src/mdtest_snippet.py:28:14
| |
27 | # error: [not-iterable] 27 | # error: [not-iterable]
28 | for x in Iterable1(): 28 | for x in Iterable1():
| ^^^^^^^^^^^ Object of type `Iterable1` may not be iterable because its `__iter__` method returns an object of type `Iterator1`, which may have an invalid `__next__` method (expected `def __next__(self): ...`) | ^^^^^^^^^^^
29 | reveal_type(x) # revealed: int | str 29 | reveal_type(x) # revealed: int | str
| |
@ -77,12 +77,12 @@ info: revealed-type: Revealed type
``` ```
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable2` may not be iterable because its `__iter__` method returns an object of type `Iterator2`, which has a `__next__` attribute that may not be callable
--> /src/mdtest_snippet.py:32:14 --> /src/mdtest_snippet.py:32:14
| |
31 | # error: [not-iterable] 31 | # error: [not-iterable]
32 | for y in Iterable2(): 32 | for y in Iterable2():
| ^^^^^^^^^^^ Object of type `Iterable2` may not be iterable because its `__iter__` method returns an object of type `Iterator2`, which has a `__next__` attribute that may not be callable | ^^^^^^^^^^^
33 | # TODO: `int` would probably be better here: 33 | # TODO: `int` would probably be better here:
34 | reveal_type(y) # revealed: int | Unknown 34 | reveal_type(y) # revealed: int | Unknown
| |

View file

@ -36,12 +36,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable` may not be iterable because it may not have an `__iter__` method and its `__getitem__` method has an incorrect signature for the old-style iteration protocol (expected a signature at least as permissive as `def __getitem__(self, key: int): ...`)
--> /src/mdtest_snippet.py:18:14 --> /src/mdtest_snippet.py:18:14
| |
17 | # error: [not-iterable] 17 | # error: [not-iterable]
18 | for x in Iterable(): 18 | for x in Iterable():
| ^^^^^^^^^^ Object of type `Iterable` may not be iterable because it may not have an `__iter__` method and its `__getitem__` method has an incorrect signature for the old-style iteration protocol (expected a signature at least as permissive as `def __getitem__(self, key: int): ...`) | ^^^^^^^^^^
19 | reveal_type(x) # revealed: int | bytes 19 | reveal_type(x) # revealed: int | bytes
| |

View file

@ -54,12 +54,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable1` may not be iterable because it may not have an `__iter__` method and its `__getitem__` attribute (with type `(bound method Iterable1.__getitem__(item: int) -> str) | None`) may not be callable
--> /src/mdtest_snippet.py:31:14 --> /src/mdtest_snippet.py:31:14
| |
30 | # error: [not-iterable] 30 | # error: [not-iterable]
31 | for x in Iterable1(): 31 | for x in Iterable1():
| ^^^^^^^^^^^ Object of type `Iterable1` may not be iterable because it may not have an `__iter__` method and its `__getitem__` attribute (with type `(bound method Iterable1.__getitem__(item: int) -> str) | None`) may not be callable | ^^^^^^^^^^^
32 | # TODO: `bytes | str` might be better 32 | # TODO: `bytes | str` might be better
33 | reveal_type(x) # revealed: bytes | str | Unknown 33 | reveal_type(x) # revealed: bytes | str | Unknown
| |
@ -81,12 +81,12 @@ info: revealed-type: Revealed type
``` ```
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable2` may not be iterable because it may not have an `__iter__` method and its `__getitem__` method (with type `(bound method Iterable2.__getitem__(item: int) -> str) | (bound method Iterable2.__getitem__(item: str) -> int)`) may have an incorrect signature for the old-style iteration protocol (expected a signature at least as permissive as `def __getitem__(self, key: int): ...`)
--> /src/mdtest_snippet.py:36:14 --> /src/mdtest_snippet.py:36:14
| |
35 | # error: [not-iterable] 35 | # error: [not-iterable]
36 | for y in Iterable2(): 36 | for y in Iterable2():
| ^^^^^^^^^^^ Object of type `Iterable2` may not be iterable because it may not have an `__iter__` method and its `__getitem__` method (with type `(bound method Iterable2.__getitem__(item: int) -> str) | (bound method Iterable2.__getitem__(item: str) -> int)`) may have an incorrect signature for the old-style iteration protocol (expected a signature at least as permissive as `def __getitem__(self, key: int): ...`) | ^^^^^^^^^^^
37 | reveal_type(y) # revealed: bytes | str | int 37 | reveal_type(y) # revealed: bytes | str | int
| |

View file

@ -35,12 +35,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable` may not be iterable because it may not have an `__iter__` method or a `__getitem__` method
--> /src/mdtest_snippet.py:17:14 --> /src/mdtest_snippet.py:17:14
| |
16 | # error: [not-iterable] 16 | # error: [not-iterable]
17 | for x in Iterable(): 17 | for x in Iterable():
| ^^^^^^^^^^ Object of type `Iterable` may not be iterable because it may not have an `__iter__` method or a `__getitem__` method | ^^^^^^^^^^
18 | reveal_type(x) # revealed: int | bytes 18 | reveal_type(x) # revealed: int | bytes
| |

View file

@ -36,13 +36,13 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Test | Test2` may not be iterable because its `__iter__` method returns an object of type `TestIter | int`, which may not have a `__next__` method
--> /src/mdtest_snippet.py:18:14 --> /src/mdtest_snippet.py:18:14
| |
16 | # TODO: Improve error message to state which union variant isn't iterable (https://github.com/astral-sh/ruff/issues/13989) 16 | # TODO: Improve error message to state which union variant isn't iterable (https://github.com/astral-sh/ruff/issues/13989)
17 | # error: [not-iterable] 17 | # error: [not-iterable]
18 | for x in Test() if flag else Test2(): 18 | for x in Test() if flag else Test2():
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Object of type `Test | Test2` may not be iterable because its `__iter__` method returns an object of type `TestIter | int`, which may not have a `__next__` method | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
19 | reveal_type(x) # revealed: int 19 | reveal_type(x) # revealed: int
| |

View file

@ -31,13 +31,13 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Test | Literal[42]` may not be iterable because it may not have an `__iter__` method and it doesn't have a `__getitem__` method
--> /src/mdtest_snippet.py:13:14 --> /src/mdtest_snippet.py:13:14
| |
11 | def _(flag: bool): 11 | def _(flag: bool):
12 | # error: [not-iterable] 12 | # error: [not-iterable]
13 | for x in Test() if flag else 42: 13 | for x in Test() if flag else 42:
| ^^^^^^^^^^^^^^^^^^^^^^ Object of type `Test | Literal[42]` may not be iterable because it may not have an `__iter__` method and it doesn't have a `__getitem__` method | ^^^^^^^^^^^^^^^^^^^^^^
14 | reveal_type(x) # revealed: int 14 | reveal_type(x) # revealed: int
| |

View file

@ -33,12 +33,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `NotIterable` is not iterable because its `__iter__` attribute has type `int | None`, which is not callable
--> /src/mdtest_snippet.py:11:14 --> /src/mdtest_snippet.py:11:14
| |
10 | # error: [not-iterable] 10 | # error: [not-iterable]
11 | for x in NotIterable(): 11 | for x in NotIterable():
| ^^^^^^^^^^^^^ Object of type `NotIterable` is not iterable because its `__iter__` attribute has type `int | None`, which is not callable | ^^^^^^^^^^^^^
12 | pass 12 | pass
| |

View file

@ -26,12 +26,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Bad` is not iterable because its `__iter__` method returns an object of type `int`, which has no `__next__` method
--> /src/mdtest_snippet.py:8:10 --> /src/mdtest_snippet.py:8:10
| |
7 | # error: [not-iterable] 7 | # error: [not-iterable]
8 | for x in Bad(): 8 | for x in Bad():
| ^^^^^ Object of type `Bad` is not iterable because its `__iter__` method returns an object of type `int`, which has no `__next__` method | ^^^^^
9 | reveal_type(x) # revealed: Unknown 9 | reveal_type(x) # revealed: Unknown
| |

View file

@ -30,12 +30,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable` is not iterable because its `__iter__` method has an invalid signature (expected `def __iter__(self): ...`)
--> /src/mdtest_snippet.py:12:10 --> /src/mdtest_snippet.py:12:10
| |
11 | # error: [not-iterable] 11 | # error: [not-iterable]
12 | for x in Iterable(): 12 | for x in Iterable():
| ^^^^^^^^^^ Object of type `Iterable` is not iterable because its `__iter__` method has an invalid signature (expected `def __iter__(self): ...`) | ^^^^^^^^^^
13 | reveal_type(x) # revealed: int 13 | reveal_type(x) # revealed: int
| |

View file

@ -41,12 +41,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/loops/for.md
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable1` is not iterable because its `__iter__` method returns an object of type `Iterator1`, which has an invalid `__next__` method (expected `def __next__(self): ...`)
--> /src/mdtest_snippet.py:19:10 --> /src/mdtest_snippet.py:19:10
| |
18 | # error: [not-iterable] 18 | # error: [not-iterable]
19 | for x in Iterable1(): 19 | for x in Iterable1():
| ^^^^^^^^^^^ Object of type `Iterable1` is not iterable because its `__iter__` method returns an object of type `Iterator1`, which has an invalid `__next__` method (expected `def __next__(self): ...`) | ^^^^^^^^^^^
20 | reveal_type(x) # revealed: int 20 | reveal_type(x) # revealed: int
| |
@ -67,12 +67,12 @@ info: revealed-type: Revealed type
``` ```
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Iterable2` is not iterable because its `__iter__` method returns an object of type `Iterator2`, which has a `__next__` attribute that is not callable
--> /src/mdtest_snippet.py:23:10 --> /src/mdtest_snippet.py:23:10
| |
22 | # error: [not-iterable] 22 | # error: [not-iterable]
23 | for y in Iterable2(): 23 | for y in Iterable2():
| ^^^^^^^^^^^ Object of type `Iterable2` is not iterable because its `__iter__` method returns an object of type `Iterator2`, which has a `__next__` attribute that is not callable | ^^^^^^^^^^^
24 | reveal_type(y) # revealed: Unknown 24 | reveal_type(y) # revealed: Unknown
| |

View file

@ -24,12 +24,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/binary/instances.m
# Diagnostics # Diagnostics
``` ```
error: lint:unsupported-bool-conversion error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable
--> /src/mdtest_snippet.py:7:8 --> /src/mdtest_snippet.py:7:8
| |
6 | # error: [unsupported-bool-conversion] 6 | # error: [unsupported-bool-conversion]
7 | 10 and a and True 7 | 10 and a and True
| ^ Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable | ^
| |
``` ```

View file

@ -28,12 +28,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/comparison/instanc
# Diagnostics # Diagnostics
``` ```
error: lint:unsupported-bool-conversion error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable
--> /src/mdtest_snippet.py:9:1 --> /src/mdtest_snippet.py:9:1
| |
8 | # error: [unsupported-bool-conversion] 8 | # error: [unsupported-bool-conversion]
9 | 10 in WithContains() 9 | 10 in WithContains()
| ^^^^^^^^^^^^^^^^^^^^ Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable | ^^^^^^^^^^^^^^^^^^^^
10 | # error: [unsupported-bool-conversion] 10 | # error: [unsupported-bool-conversion]
11 | 10 not in WithContains() 11 | 10 not in WithContains()
| |
@ -41,13 +41,13 @@ error: lint:unsupported-bool-conversion
``` ```
``` ```
error: lint:unsupported-bool-conversion error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable
--> /src/mdtest_snippet.py:11:1 --> /src/mdtest_snippet.py:11:1
| |
9 | 10 in WithContains() 9 | 10 in WithContains()
10 | # error: [unsupported-bool-conversion] 10 | # error: [unsupported-bool-conversion]
11 | 10 not in WithContains() 11 | 10 not in WithContains()
| ^^^^^^^^^^^^^^^^^^^^^^^^ Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable | ^^^^^^^^^^^^^^^^^^^^^^^^
| |
``` ```

View file

@ -22,12 +22,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/unary/not.md
# Diagnostics # Diagnostics
``` ```
error: lint:unsupported-bool-conversion error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable
--> /src/mdtest_snippet.py:5:1 --> /src/mdtest_snippet.py:5:1
| |
4 | # error: [unsupported-bool-conversion] 4 | # error: [unsupported-bool-conversion]
5 | not NotBoolable() 5 | not NotBoolable()
| ^^^^^^^^^^^^^^^^^ Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable | ^^^^^^^^^^^^^^^^^
| |
``` ```

View file

@ -33,12 +33,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/comparison/instanc
# Diagnostics # Diagnostics
``` ```
error: lint:unsupported-bool-conversion error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable
--> /src/mdtest_snippet.py:12:1 --> /src/mdtest_snippet.py:12:1
| |
11 | # error: [unsupported-bool-conversion] 11 | # error: [unsupported-bool-conversion]
12 | 10 < Comparable() < 20 12 | 10 < Comparable() < 20
| ^^^^^^^^^^^^^^^^^ Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable | ^^^^^^^^^^^^^^^^^
13 | # error: [unsupported-bool-conversion] 13 | # error: [unsupported-bool-conversion]
14 | 10 < Comparable() < Comparable() 14 | 10 < Comparable() < Comparable()
| |
@ -46,13 +46,13 @@ error: lint:unsupported-bool-conversion
``` ```
``` ```
error: lint:unsupported-bool-conversion error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable
--> /src/mdtest_snippet.py:14:1 --> /src/mdtest_snippet.py:14:1
| |
12 | 10 < Comparable() < 20 12 | 10 < Comparable() < 20
13 | # error: [unsupported-bool-conversion] 13 | # error: [unsupported-bool-conversion]
14 | 10 < Comparable() < Comparable() 14 | 10 < Comparable() < Comparable()
| ^^^^^^^^^^^^^^^^^ Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable | ^^^^^^^^^^^^^^^^^
15 | 15 |
16 | Comparable() < Comparable() # fine 16 | Comparable() < Comparable() # fine
| |

View file

@ -34,12 +34,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/comparison/tuples.
# Diagnostics # Diagnostics
``` ```
error: lint:unsupported-bool-conversion error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable | Literal[False]`; its `__bool__` method isn't callable
--> /src/mdtest_snippet.py:15:1 --> /src/mdtest_snippet.py:15:1
| |
14 | # error: [unsupported-bool-conversion] 14 | # error: [unsupported-bool-conversion]
15 | a < b < b 15 | a < b < b
| ^^^^^ Boolean conversion is unsupported for type `NotBoolable | Literal[False]`; its `__bool__` method isn't callable | ^^^^^
16 | 16 |
17 | a < b # fine 17 | a < b # fine
| |

View file

@ -26,12 +26,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/comparison/tuples.
# Diagnostics # Diagnostics
``` ```
error: lint:unsupported-bool-conversion error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable
--> /src/mdtest_snippet.py:9:1 --> /src/mdtest_snippet.py:9:1
| |
8 | # error: [unsupported-bool-conversion] 8 | # error: [unsupported-bool-conversion]
9 | (A(),) == (A(),) 9 | (A(),) == (A(),)
| ^^^^^^^^^^^^^^^^ Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable | ^^^^^^^^^^^^^^^^
| |
``` ```

View file

@ -18,11 +18,11 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/unpack
# Diagnostics # Diagnostics
``` ```
error: lint:not-iterable error: lint:not-iterable: Object of type `Literal[1]` is not iterable because it doesn't have an `__iter__` method or a `__getitem__` method
--> /src/mdtest_snippet.py:1:8 --> /src/mdtest_snippet.py:1:8
| |
1 | a, b = 1 # error: [not-iterable] 1 | a, b = 1 # error: [not-iterable]
| ^ Object of type `Literal[1]` is not iterable because it doesn't have an `__iter__` method or a `__getitem__` method | ^
| |
``` ```

View file

@ -5029,11 +5029,10 @@ impl<'db> InvalidTypeExpressionError<'db> {
} = self; } = self;
if is_reachable { if is_reachable {
for error in invalid_expressions { for error in invalid_expressions {
context.report_lint_old( let Some(builder) = context.report_lint(&INVALID_TYPE_FORM, node) else {
&INVALID_TYPE_FORM, continue;
node, };
format_args!("{}", error.reason(context.db())), builder.into_diagnostic(error.reason(context.db()));
);
} }
} }
fallback_type fallback_type
@ -5218,6 +5217,11 @@ impl<'db> ContextManagerError<'db> {
context_expression_type: Type<'db>, context_expression_type: Type<'db>,
context_expression_node: ast::AnyNodeRef, context_expression_node: ast::AnyNodeRef,
) { ) {
let Some(builder) = context.report_lint(&INVALID_CONTEXT_MANAGER, context_expression_node)
else {
return;
};
let format_call_dunder_error = |call_dunder_error: &CallDunderError<'db>, name: &str| { let format_call_dunder_error = |call_dunder_error: &CallDunderError<'db>, name: &str| {
match call_dunder_error { match call_dunder_error {
CallDunderError::MethodNotAvailable => format!("it does not implement `{name}`"), CallDunderError::MethodNotAvailable => format!("it does not implement `{name}`"),
@ -5269,9 +5273,7 @@ impl<'db> ContextManagerError<'db> {
} => format_call_dunder_errors(enter_error, "__enter__", exit_error, "__exit__"), } => format_call_dunder_errors(enter_error, "__enter__", exit_error, "__exit__"),
}; };
context.report_lint_old( builder.into_diagnostic(
&INVALID_CONTEXT_MANAGER,
context_expression_node,
format_args!( format_args!(
"Object of type `{context_expression}` cannot be used with `with` because {formatted_errors}", "Object of type `{context_expression}` cannot be used with `with` because {formatted_errors}",
context_expression = context_expression_type.display(db) context_expression = context_expression_type.display(db)
@ -5369,10 +5371,13 @@ impl<'db> IterationError<'db> {
iterable_type: Type<'db>, iterable_type: Type<'db>,
iterable_node: ast::AnyNodeRef, iterable_node: ast::AnyNodeRef,
) { ) {
let Some(builder) = context.report_lint(&NOT_ITERABLE, iterable_node) else {
return;
};
let db = context.db(); let db = context.db();
let report_not_iterable = |arguments: std::fmt::Arguments| { let report_not_iterable = |arguments: std::fmt::Arguments| {
context.report_lint_old(&NOT_ITERABLE, iterable_node, arguments); builder.into_diagnostic(arguments);
}; };
// TODO: for all of these error variants, the "explanation" for the diagnostic // TODO: for all of these error variants, the "explanation" for the diagnostic
@ -5646,13 +5651,14 @@ impl<'db> BoolError<'db> {
} }
fn report_diagnostic_impl(&self, context: &InferContext, condition: TextRange) { fn report_diagnostic_impl(&self, context: &InferContext, condition: TextRange) {
let Some(builder) = context.report_lint(&UNSUPPORTED_BOOL_CONVERSION, condition) else {
return;
};
match self { match self {
Self::IncorrectArguments { Self::IncorrectArguments {
not_boolable_type, .. not_boolable_type, ..
} => { } => {
context.report_lint_old( builder.into_diagnostic(
&UNSUPPORTED_BOOL_CONVERSION,
condition,
format_args!( format_args!(
"Boolean conversion is unsupported for type `{}`; it incorrectly implements `__bool__`", "Boolean conversion is unsupported for type `{}`; it incorrectly implements `__bool__`",
not_boolable_type.display(context.db()) not_boolable_type.display(context.db())
@ -5663,25 +5669,20 @@ impl<'db> BoolError<'db> {
not_boolable_type, not_boolable_type,
return_type, return_type,
} => { } => {
context.report_lint_old( builder.into_diagnostic(format_args!(
&UNSUPPORTED_BOOL_CONVERSION, "Boolean conversion is unsupported for type `{not_boolable}`; \
condition, the return type of its bool method (`{return_type}`) \
format_args!( isn't assignable to `bool",
"Boolean conversion is unsupported for type `{not_boolable}`; the return type of its bool method (`{return_type}`) isn't assignable to `bool",
not_boolable = not_boolable_type.display(context.db()), not_boolable = not_boolable_type.display(context.db()),
return_type = return_type.display(context.db()) return_type = return_type.display(context.db())
), ));
);
} }
Self::NotCallable { not_boolable_type } => { Self::NotCallable { not_boolable_type } => {
context.report_lint_old( builder.into_diagnostic(format_args!(
&UNSUPPORTED_BOOL_CONVERSION, "Boolean conversion is unsupported for type `{}`; \
condition, its `__bool__` method isn't callable",
format_args!(
"Boolean conversion is unsupported for type `{}`; its `__bool__` method isn't callable",
not_boolable_type.display(context.db()) not_boolable_type.display(context.db())
), ));
);
} }
Self::Union { union, .. } => { Self::Union { union, .. } => {
let first_error = union let first_error = union
@ -5690,26 +5691,20 @@ impl<'db> BoolError<'db> {
.find_map(|element| element.try_bool(context.db()).err()) .find_map(|element| element.try_bool(context.db()).err())
.unwrap(); .unwrap();
context.report_lint_old( builder.into_diagnostic(format_args!(
&UNSUPPORTED_BOOL_CONVERSION, "Boolean conversion is unsupported for union `{}` \
condition, because `{}` doesn't implement `__bool__` correctly",
format_args!(
"Boolean conversion is unsupported for union `{}` because `{}` doesn't implement `__bool__` correctly",
Type::Union(*union).display(context.db()), Type::Union(*union).display(context.db()),
first_error.not_boolable_type().display(context.db()), first_error.not_boolable_type().display(context.db()),
), ));
);
} }
Self::Other { not_boolable_type } => { Self::Other { not_boolable_type } => {
context.report_lint_old( builder.into_diagnostic(format_args!(
&UNSUPPORTED_BOOL_CONVERSION, "Boolean conversion is unsupported for type `{}`; \
condition, it incorrectly implements `__bool__`",
format_args!(
"Boolean conversion is unsupported for type `{}`; it incorrectly implements `__bool__`",
not_boolable_type.display(context.db()) not_boolable_type.display(context.db())
), ));
);
} }
} }
} }
@ -5740,27 +5735,28 @@ impl<'db> ConstructorCallError<'db> {
) { ) {
let report_init_error = |call_dunder_error: &CallDunderError<'db>| match call_dunder_error { let report_init_error = |call_dunder_error: &CallDunderError<'db>| match call_dunder_error {
CallDunderError::MethodNotAvailable => { CallDunderError::MethodNotAvailable => {
if let Some(builder) =
context.report_lint(&CALL_POSSIBLY_UNBOUND_METHOD, context_expression_node)
{
// If we are using vendored typeshed, it should be impossible to have missing // If we are using vendored typeshed, it should be impossible to have missing
// or unbound `__init__` method on a class, as all classes have `object` in MRO. // or unbound `__init__` method on a class, as all classes have `object` in MRO.
// Thus the following may only trigger if a custom typeshed is used. // Thus the following may only trigger if a custom typeshed is used.
context.report_lint_old( builder.into_diagnostic(format_args!(
&CALL_POSSIBLY_UNBOUND_METHOD, "`__init__` method is missing on type `{}`. \
context_expression_node, Make sure your `object` in typeshed has its definition.",
format_args!(
"`__init__` method is missing on type `{}`. Make sure your `object` in typeshed has its definition.",
context_expression_type.display(context.db()), context_expression_type.display(context.db()),
), ));
); }
} }
CallDunderError::PossiblyUnbound(bindings) => { CallDunderError::PossiblyUnbound(bindings) => {
context.report_lint_old( if let Some(builder) =
&CALL_POSSIBLY_UNBOUND_METHOD, context.report_lint(&CALL_POSSIBLY_UNBOUND_METHOD, context_expression_node)
context_expression_node, {
format_args!( builder.into_diagnostic(format_args!(
"Method `__init__` on type `{}` is possibly unbound.", "Method `__init__` on type `{}` is possibly unbound.",
context_expression_type.display(context.db()), context_expression_type.display(context.db()),
), ));
); }
bindings.report_diagnostics(context, context_expression_node); bindings.report_diagnostics(context, context_expression_node);
} }
@ -5776,14 +5772,14 @@ impl<'db> ConstructorCallError<'db> {
unreachable!("`__new__` method may not be called if missing"); unreachable!("`__new__` method may not be called if missing");
} }
CallDunderError::PossiblyUnbound(bindings) => { CallDunderError::PossiblyUnbound(bindings) => {
context.report_lint_old( if let Some(builder) =
&CALL_POSSIBLY_UNBOUND_METHOD, context.report_lint(&CALL_POSSIBLY_UNBOUND_METHOD, context_expression_node)
context_expression_node, {
format_args!( builder.into_diagnostic(format_args!(
"Method `__new__` on type `{}` is possibly unbound.", "Method `__new__` on type `{}` is possibly unbound.",
context_expression_type.display(context.db()), context_expression_type.display(context.db()),
), ));
); }
bindings.report_diagnostics(context, context_expression_node); bindings.report_diagnostics(context, context_expression_node);
} }
@ -7130,34 +7126,31 @@ impl BoundSuperError<'_> {
pub(super) fn report_diagnostic(&self, context: &InferContext, node: AnyNodeRef) { pub(super) fn report_diagnostic(&self, context: &InferContext, node: AnyNodeRef) {
match self { match self {
BoundSuperError::InvalidPivotClassType { pivot_class } => { BoundSuperError::InvalidPivotClassType { pivot_class } => {
context.report_lint_old( if let Some(builder) = context.report_lint(&INVALID_SUPER_ARGUMENT, node) {
&INVALID_SUPER_ARGUMENT, builder.into_diagnostic(format_args!(
node,
format_args!(
"`{pivot_class}` is not a valid class", "`{pivot_class}` is not a valid class",
pivot_class = pivot_class.display(context.db()), pivot_class = pivot_class.display(context.db()),
), ));
); }
} }
BoundSuperError::FailingConditionCheck { pivot_class, owner } => { BoundSuperError::FailingConditionCheck { pivot_class, owner } => {
context.report_lint_old( if let Some(builder) = context.report_lint(&INVALID_SUPER_ARGUMENT, node) {
&INVALID_SUPER_ARGUMENT, builder.into_diagnostic(format_args!(
node, "`{owner}` is not an instance or subclass of \
format_args!( `{pivot_class}` in `super({pivot_class}, {owner})` call",
"`{owner}` is not an instance or subclass of `{pivot_class}` in `super({pivot_class}, {owner})` call",
pivot_class = pivot_class.display(context.db()), pivot_class = pivot_class.display(context.db()),
owner = owner.display(context.db()), owner = owner.display(context.db()),
), ));
); }
} }
BoundSuperError::UnavailableImplicitArguments => { BoundSuperError::UnavailableImplicitArguments => {
context.report_lint_old( if let Some(builder) =
&UNAVAILABLE_IMPLICIT_SUPER_ARGUMENTS, context.report_lint(&UNAVAILABLE_IMPLICIT_SUPER_ARGUMENTS, node)
node, {
format_args!( builder.into_diagnostic(format_args!(
"Cannot determine implicit arguments for 'super()' in this context", "Cannot determine implicit arguments for 'super()' in this context",
), ));
); }
} }
} }
} }