diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Data_descriptors_-_Invalid_`__set__`_method_signature.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Data_descriptors_-_Invalid_`__set__`_method_signature.snap index 2914deba0c..8f46e05fac 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Data_descriptors_-_Invalid_`__set__`_method_signature.snap +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Data_descriptors_-_Invalid_`__set__`_method_signature.snap @@ -28,12 +28,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/attrib # Diagnostics ``` -error: lint:invalid-assignment +error: lint:invalid-assignment: Invalid assignment to data descriptor attribute `attr` on type `C` with custom `__set__` method --> /src/mdtest_snippet.py:11:1 | 10 | # TODO: ideally, we would mention why this is an invalid assignment (wrong number of arguments for `__set__`) 11 | instance.attr = 1 # error: [invalid-assignment] - | ^^^^^^^^^^^^^ Invalid assignment to data descriptor attribute `attr` on type `C` with custom `__set__` method + | ^^^^^^^^^^^^^ | ``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Data_descriptors_-_Invalid_argument_type.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Data_descriptors_-_Invalid_argument_type.snap index 90b4a81494..0b8d3b4434 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Data_descriptors_-_Invalid_argument_type.snap +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Data_descriptors_-_Invalid_argument_type.snap @@ -29,12 +29,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/attrib # Diagnostics ``` -error: lint:invalid-assignment +error: lint:invalid-assignment: Invalid assignment to data descriptor attribute `attr` on type `C` with custom `__set__` method --> /src/mdtest_snippet.py:12:1 | 11 | # TODO: ideally, we would mention why this is an invalid assignment (wrong argument type for `value` parameter) 12 | instance.attr = "wrong" # error: [invalid-assignment] - | ^^^^^^^^^^^^^ Invalid assignment to data descriptor attribute `attr` on type `C` with custom `__set__` method + | ^^^^^^^^^^^^^ | ``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Setting_attributes_on_union_types.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Setting_attributes_on_union_types.snap index ec479c5896..92606ccb68 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Setting_attributes_on_union_types.snap +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Setting_attributes_on_union_types.snap @@ -37,12 +37,12 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/attrib # Diagnostics ``` -error: lint:invalid-assignment +error: lint:invalid-assignment: Object of type `Literal[1]` is not assignable to attribute `attr` on type `Literal[C1, C1]` --> /src/mdtest_snippet.py:11:5 | 10 | # TODO: The error message here could be improved to explain why the assignment fails. 11 | C1.attr = 1 # error: [invalid-assignment] - | ^^^^^^^ Object of type `Literal[1]` is not assignable to attribute `attr` on type `Literal[C1, C1]` + | ^^^^^^^ 12 | 13 | class C2: | diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index d2649620dc..175bddff08 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -2442,13 +2442,17 @@ impl<'db> TypeInferenceBuilder<'db> { true } else { // TODO: This is not a very helpful error message, as it does not include the underlying reason - // why the assignment is invalid. This would be a good use case for nested diagnostics. + // why the assignment is invalid. This would be a good use case for sub-diagnostics. if emit_diagnostics { - self.context.report_lint_old(&INVALID_ASSIGNMENT, target, format_args!( - "Object of type `{}` is not assignable to attribute `{attribute}` on type `{}`", - value_ty.display(self.db()), - object_ty.display(self.db()), - )); + if let Some(builder) = self.context.report_lint(&INVALID_ASSIGNMENT, target) + { + builder.into_diagnostic(format_args!( + "Object of type `{}` is not assignable \ + to attribute `{attribute}` on type `{}`", + value_ty.display(self.db()), + object_ty.display(self.db()), + )); + } } false @@ -2463,12 +2467,16 @@ impl<'db> TypeInferenceBuilder<'db> { true } else { if emit_diagnostics { - // TODO: same here, see above - self.context.report_lint_old(&INVALID_ASSIGNMENT, target, format_args!( - "Object of type `{}` is not assignable to attribute `{attribute}` on type `{}`", - value_ty.display(self.db()), - object_ty.display(self.db()), - )); + if let Some(builder) = self.context.report_lint(&INVALID_ASSIGNMENT, target) + { + // TODO: same here, see above + builder.into_diagnostic(format_args!( + "Object of type `{}` is not assignable \ + to attribute `{attribute}` on type `{}`", + value_ty.display(self.db()), + object_ty.display(self.db()), + )); + } } false } @@ -2557,15 +2565,16 @@ impl<'db> TypeInferenceBuilder<'db> { .is_ok(); if !successful_call && emit_diagnostics { - // TODO: Here, it would be nice to emit an additional diagnostic that explains why the call failed - self.context.report_lint_old( - &INVALID_ASSIGNMENT, - target, - format_args!( - "Invalid assignment to data descriptor attribute `{attribute}` on type `{}` with custom `__set__` method", - object_ty.display(db) - ), - ); + if let Some(builder) = + self.context.report_lint(&INVALID_ASSIGNMENT, target) + { + // TODO: Here, it would be nice to emit an additional diagnostic that explains why the call failed + builder.into_diagnostic(format_args!( + "Invalid assignment to data descriptor attribute \ + `{attribute}` on type `{}` with custom `__set__` method", + object_ty.display(db) + )); + } } successful_call @@ -2695,15 +2704,16 @@ impl<'db> TypeInferenceBuilder<'db> { .is_ok(); if !successful_call && emit_diagnostics { - // TODO: Here, it would be nice to emit an additional diagnostic that explains why the call failed - self.context.report_lint_old( - &INVALID_ASSIGNMENT, - target, - format_args!( - "Invalid assignment to data descriptor attribute `{attribute}` on type `{}` with custom `__set__` method", + if let Some(builder) = + self.context.report_lint(&INVALID_ASSIGNMENT, target) + { + // TODO: Here, it would be nice to emit an additional diagnostic that explains why the call failed + builder.into_diagnostic(format_args!( + "Invalid assignment to data descriptor attribute \ + `{attribute}` on type `{}` with custom `__set__` method", object_ty.display(db) - ), - ); + )); + } } successful_call