From 6dc2d29966dd0e691eb3dc037e94ae33e21552f8 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Wed, 16 Apr 2025 10:29:41 -0400 Subject: [PATCH] red_knot_python_semantic: migrate INVALID_ASSIGNMENT for shadowing We mostly keep things the same here, but the message has been moved from the annotation to the diagnostic's top-line message. I think this is perhaps a little worse, but some bigger improvements could be made here. Indeed, we could perhaps even add a "fix" here. --- .../resources/mdtest/diagnostics/shadowing.md | 19 +++++++++++ .../resources/mdtest/shadowing/class.md | 2 +- .../resources/mdtest/shadowing/function.md | 2 +- ..._attributes_with_class-level_defaults.snap | 8 ++--- ...assignment_-_Pure_instance_attributes.snap | 4 +-- ..._-_Attribute_assignment_-_`ClassVar`s.snap | 4 +-- ..._Shadowing_-_Implicit_class_shadowing.snap | 33 +++++++++++++++++++ ...adowing_-_Implicit_function_shadowing.snap | 33 +++++++++++++++++++ .../src/types/diagnostic.rs | 21 ++++++++---- 9 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 crates/red_knot_python_semantic/resources/mdtest/diagnostics/shadowing.md create mode 100644 crates/red_knot_python_semantic/resources/mdtest/snapshots/shadowing.md_-_Shadowing_-_Implicit_class_shadowing.snap create mode 100644 crates/red_knot_python_semantic/resources/mdtest/snapshots/shadowing.md_-_Shadowing_-_Implicit_function_shadowing.snap diff --git a/crates/red_knot_python_semantic/resources/mdtest/diagnostics/shadowing.md b/crates/red_knot_python_semantic/resources/mdtest/diagnostics/shadowing.md new file mode 100644 index 0000000000..c63631c1e4 --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/diagnostics/shadowing.md @@ -0,0 +1,19 @@ +# Shadowing + + + +## Implicit class shadowing + +```py +class C: ... + +C = 1 # error: [invalid-assignment] +``` + +## Implicit function shadowing + +```py +def f(): ... + +f = 1 # error: [invalid-assignment] +``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/shadowing/class.md b/crates/red_knot_python_semantic/resources/mdtest/shadowing/class.md index 212c97baf9..97550ec57c 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/shadowing/class.md +++ b/crates/red_knot_python_semantic/resources/mdtest/shadowing/class.md @@ -5,7 +5,7 @@ ```py class C: ... -C = 1 # error: "Implicit shadowing of class `C`; annotate to make it explicit if this is intentional" +C = 1 # error: "Implicit shadowing of class `C`" ``` ## Explicit diff --git a/crates/red_knot_python_semantic/resources/mdtest/shadowing/function.md b/crates/red_knot_python_semantic/resources/mdtest/shadowing/function.md index ea976c3593..dda365e13a 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/shadowing/function.md +++ b/crates/red_knot_python_semantic/resources/mdtest/shadowing/function.md @@ -15,7 +15,7 @@ def f(x: str): ```py def f(): ... -f = 1 # error: "Implicit shadowing of function `f`; annotate to make it explicit if this is intentional" +f = 1 # error: "Implicit shadowing of function `f`" ``` ## Explicit shadowing diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Instance_attributes_with_class-level_defaults.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Instance_attributes_with_class-level_defaults.snap index eb06b09308..8ea6c93874 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Instance_attributes_with_class-level_defaults.snap +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Instance_attributes_with_class-level_defaults.snap @@ -26,13 +26,13 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/attrib # Diagnostics ``` -error: lint:invalid-assignment +error: lint:invalid-assignment: Object of type `Literal["wrong"]` is not assignable to attribute `attr` of type `int` --> /src/mdtest_snippet.py:6:1 | 4 | instance = C() 5 | instance.attr = 1 # fine 6 | instance.attr = "wrong" # error: [invalid-assignment] - | ^^^^^^^^^^^^^ Object of type `Literal["wrong"]` is not assignable to attribute `attr` of type `int` + | ^^^^^^^^^^^^^ 7 | 8 | C.attr = 1 # fine | @@ -40,12 +40,12 @@ error: lint:invalid-assignment ``` ``` -error: lint:invalid-assignment +error: lint:invalid-assignment: Object of type `Literal["wrong"]` is not assignable to attribute `attr` of type `int` --> /src/mdtest_snippet.py:9:1 | 8 | C.attr = 1 # fine 9 | C.attr = "wrong" # error: [invalid-assignment] - | ^^^^^^ Object of type `Literal["wrong"]` is not assignable to attribute `attr` of type `int` + | ^^^^^^ | ``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Pure_instance_attributes.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Pure_instance_attributes.snap index 78fe6d1da5..a1e4f9274a 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Pure_instance_attributes.snap +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_Pure_instance_attributes.snap @@ -26,13 +26,13 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/attrib # Diagnostics ``` -error: lint:invalid-assignment +error: lint:invalid-assignment: Object of type `Literal["wrong"]` is not assignable to attribute `attr` of type `int` --> /src/mdtest_snippet.py:7:1 | 5 | instance = C() 6 | instance.attr = 1 # fine 7 | instance.attr = "wrong" # error: [invalid-assignment] - | ^^^^^^^^^^^^^ Object of type `Literal["wrong"]` is not assignable to attribute `attr` of type `int` + | ^^^^^^^^^^^^^ 8 | 9 | C.attr = 1 # error: [invalid-attribute-access] | diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_`ClassVar`s.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_`ClassVar`s.snap index 59389d2036..573d8937ad 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_`ClassVar`s.snap +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/attribute_assignment.md_-_Attribute_assignment_-_`ClassVar`s.snap @@ -27,12 +27,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["wrong"]` is not assignable to attribute `attr` of type `int` --> /src/mdtest_snippet.py:7:1 | 6 | C.attr = 1 # fine 7 | C.attr = "wrong" # error: [invalid-assignment] - | ^^^^^^ Object of type `Literal["wrong"]` is not assignable to attribute `attr` of type `int` + | ^^^^^^ 8 | 9 | instance = C() | diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/shadowing.md_-_Shadowing_-_Implicit_class_shadowing.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/shadowing.md_-_Shadowing_-_Implicit_class_shadowing.snap new file mode 100644 index 0000000000..74d8fb95bb --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/shadowing.md_-_Shadowing_-_Implicit_class_shadowing.snap @@ -0,0 +1,33 @@ +--- +source: crates/red_knot_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: shadowing.md - Shadowing - Implicit class shadowing +mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/shadowing.md +--- + +# Python source files + +## mdtest_snippet.py + +``` +1 | class C: ... +2 | +3 | C = 1 # error: [invalid-assignment] +``` + +# Diagnostics + +``` +error: lint:invalid-assignment: Implicit shadowing of class `C` + --> /src/mdtest_snippet.py:3:1 + | +1 | class C: ... +2 | +3 | C = 1 # error: [invalid-assignment] + | ^ + | +info: Annotate to make it explicit if this is intentional + +``` diff --git a/crates/red_knot_python_semantic/resources/mdtest/snapshots/shadowing.md_-_Shadowing_-_Implicit_function_shadowing.snap b/crates/red_knot_python_semantic/resources/mdtest/snapshots/shadowing.md_-_Shadowing_-_Implicit_function_shadowing.snap new file mode 100644 index 0000000000..04de7c982b --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/snapshots/shadowing.md_-_Shadowing_-_Implicit_function_shadowing.snap @@ -0,0 +1,33 @@ +--- +source: crates/red_knot_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: shadowing.md - Shadowing - Implicit function shadowing +mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/shadowing.md +--- + +# Python source files + +## mdtest_snippet.py + +``` +1 | def f(): ... +2 | +3 | f = 1 # error: [invalid-assignment] +``` + +# Diagnostics + +``` +error: lint:invalid-assignment: Implicit shadowing of function `f` + --> /src/mdtest_snippet.py:3:1 + | +1 | def f(): ... +2 | +3 | f = 1 # error: [invalid-assignment] + | ^ + | +info: Annotate to make it explicit if this is intentional + +``` diff --git a/crates/red_knot_python_semantic/src/types/diagnostic.rs b/crates/red_knot_python_semantic/src/types/diagnostic.rs index 93458cd72d..f82eae4d0b 100644 --- a/crates/red_knot_python_semantic/src/types/diagnostic.rs +++ b/crates/red_knot_python_semantic/src/types/diagnostic.rs @@ -1116,19 +1116,26 @@ fn report_invalid_assignment_with_message( target_ty: Type, message: std::fmt::Arguments, ) { + let Some(builder) = context.report_lint(&INVALID_ASSIGNMENT, node) else { + return; + }; match target_ty { Type::ClassLiteral(class) => { - context.report_lint_old(&INVALID_ASSIGNMENT, node, format_args!( - "Implicit shadowing of class `{}`; annotate to make it explicit if this is intentional", - class.name(context.db()))); + let mut diag = builder.into_diagnostic(format_args!( + "Implicit shadowing of class `{}`", + class.name(context.db()), + )); + diag.info("Annotate to make it explicit if this is intentional"); } Type::FunctionLiteral(function) => { - context.report_lint_old(&INVALID_ASSIGNMENT, node, format_args!( - "Implicit shadowing of function `{}`; annotate to make it explicit if this is intentional", - function.name(context.db()))); + let mut diag = builder.into_diagnostic(format_args!( + "Implicit shadowing of function `{}`", + function.name(context.db()), + )); + diag.info("Annotate to make it explicit if this is intentional"); } _ => { - context.report_lint_old(&INVALID_ASSIGNMENT, node, message); + builder.into_diagnostic(message); } } }