diff --git a/crates/red_knot_python_semantic/resources/mdtest/diagnostics/unsupported_bool_conversion.md b/crates/red_knot_python_semantic/resources/mdtest/diagnostics/unsupported_bool_conversion.md new file mode 100644 index 0000000000..4a0d52ce98 --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/diagnostics/unsupported_bool_conversion.md @@ -0,0 +1,61 @@ + + +# Different ways that `UNSUPPORTED_BOOL_CONVERSION` can occur + +## Has a `__bool__` method, but has incorrect parameters + +```py +class NotBoolable: + def __bool__(self, foo): + return False + +a = NotBoolable() + +# error: [unsupported-bool-conversion] +10 and a and True +``` + +## Has a `__bool__` method, but has an incorrect return type + +```py +class NotBoolable: + def __bool__(self) -> str: + return "wat" + +a = NotBoolable() + +# error: [unsupported-bool-conversion] +10 and a and True +``` + +## Has a `__bool__` attribute, but it's not callable + +```py +class NotBoolable: + __bool__: int = 3 + +a = NotBoolable() + +# error: [unsupported-bool-conversion] +10 and a and True +``` + +## Part of a union where at least one member has incorrect `__bool__` method + +```py +class NotBoolable1: + def __bool__(self) -> str: + return "wat" + +class NotBoolable2: + pass + +class NotBoolable3: + __bool__: int = 3 + +def get() -> NotBoolable1 | NotBoolable2 | NotBoolable3: + return NotBoolable2() + +# error: [unsupported-bool-conversion] +10 and get() and True +``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_attribute,_but_it's_not_callable.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_attribute,_but_it's_not_callable.snap new file mode 100644 index 0000000000..2ef879a16f --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_attribute,_but_it's_not_callable.snap @@ -0,0 +1,35 @@ +--- +source: crates/red_knot_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: unsupported_bool_conversion.md - Different ways that `UNSUPPORTED_BOOL_CONVERSION` can occur - Has a `__bool__` attribute, but it's not callable +mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/unsupported_bool_conversion.md +--- + +# Python source files + +## mdtest_snippet.py + +``` +1 | class NotBoolable: +2 | __bool__: int = 3 +3 | +4 | a = NotBoolable() +5 | +6 | # error: [unsupported-bool-conversion] +7 | 10 and a and True +``` + +# Diagnostics + +``` +error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; its `__bool__` method isn't callable + --> /src/mdtest_snippet.py:7:8 + | +6 | # error: [unsupported-bool-conversion] +7 | 10 and a and True + | ^ + | + +``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_method,_but_has_an_incorrect_return_type.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_method,_but_has_an_incorrect_return_type.snap new file mode 100644 index 0000000000..2b69db7bae --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_method,_but_has_an_incorrect_return_type.snap @@ -0,0 +1,36 @@ +--- +source: crates/red_knot_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: unsupported_bool_conversion.md - Different ways that `UNSUPPORTED_BOOL_CONVERSION` can occur - Has a `__bool__` method, but has an incorrect return type +mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/unsupported_bool_conversion.md +--- + +# Python source files + +## mdtest_snippet.py + +``` +1 | class NotBoolable: +2 | def __bool__(self) -> str: +3 | return "wat" +4 | +5 | a = NotBoolable() +6 | +7 | # error: [unsupported-bool-conversion] +8 | 10 and a and True +``` + +# Diagnostics + +``` +error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; the return type of its bool method (`str`) isn't assignable to `bool + --> /src/mdtest_snippet.py:8:8 + | +7 | # error: [unsupported-bool-conversion] +8 | 10 and a and True + | ^ + | + +``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_method,_but_has_incorrect_parameters.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_method,_but_has_incorrect_parameters.snap new file mode 100644 index 0000000000..a47dc7ee5f --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Has_a_`__bool__`_method,_but_has_incorrect_parameters.snap @@ -0,0 +1,36 @@ +--- +source: crates/red_knot_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: unsupported_bool_conversion.md - Different ways that `UNSUPPORTED_BOOL_CONVERSION` can occur - Has a `__bool__` method, but has incorrect parameters +mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/unsupported_bool_conversion.md +--- + +# Python source files + +## mdtest_snippet.py + +``` +1 | class NotBoolable: +2 | def __bool__(self, foo): +3 | return False +4 | +5 | a = NotBoolable() +6 | +7 | # error: [unsupported-bool-conversion] +8 | 10 and a and True +``` + +# Diagnostics + +``` +error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for type `NotBoolable`; it incorrectly implements `__bool__` + --> /src/mdtest_snippet.py:8:8 + | +7 | # error: [unsupported-bool-conversion] +8 | 10 and a and True + | ^ + | + +``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Part_of_a_union_where_at_least_one_member_has_incorrect_`__bool__`_method.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Part_of_a_union_where_at_least_one_member_has_incorrect_`__bool__`_method.snap new file mode 100644 index 0000000000..8d33395fd2 --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/unsupported_bool_conversion.md_-_Different_ways_that_`UNSUPPORTED_BOOL_CONVERSION`_can_occur_-_Part_of_a_union_where_at_least_one_member_has_incorrect_`__bool__`_method.snap @@ -0,0 +1,43 @@ +--- +source: crates/red_knot_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: unsupported_bool_conversion.md - Different ways that `UNSUPPORTED_BOOL_CONVERSION` can occur - Part of a union where at least one member has incorrect `__bool__` method +mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/unsupported_bool_conversion.md +--- + +# Python source files + +## mdtest_snippet.py + +``` + 1 | class NotBoolable1: + 2 | def __bool__(self) -> str: + 3 | return "wat" + 4 | + 5 | class NotBoolable2: + 6 | pass + 7 | + 8 | class NotBoolable3: + 9 | __bool__: int = 3 +10 | +11 | def get() -> NotBoolable1 | NotBoolable2 | NotBoolable3: +12 | return NotBoolable2() +13 | +14 | # error: [unsupported-bool-conversion] +15 | 10 and get() and True +``` + +# Diagnostics + +``` +error: lint:unsupported-bool-conversion: Boolean conversion is unsupported for union `NotBoolable1 | NotBoolable2 | NotBoolable3` because `NotBoolable1` doesn't implement `__bool__` correctly + --> /src/mdtest_snippet.py:15:8 + | +14 | # error: [unsupported-bool-conversion] +15 | 10 and get() and True + | ^^^^^ + | + +``` diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 695353ef7b..19195f561f 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -5670,12 +5670,11 @@ impl<'db> BoolError<'db> { Self::IncorrectArguments { not_boolable_type, .. } => { - builder.into_diagnostic( - format_args!( - "Boolean conversion is unsupported for type `{}`; it incorrectly implements `__bool__`", - not_boolable_type.display(context.db()) - ), - ); + builder.into_diagnostic(format_args!( + "Boolean conversion is unsupported for type `{}`; \ + it incorrectly implements `__bool__`", + not_boolable_type.display(context.db()) + )); } Self::IncorrectReturnType { not_boolable_type,