Unnamed repository; edit this file 'description' to name the repository.
fix: respect rustc's lint attribute application order
Reverse the order of returned lint attributes for a `SyntaxNode` to match rustc's behavior. When multiple lint attributes are present, rustc overrides earlier ones with the last defined attribute. The previous iteration order was incorrect, causing earlier attributes to override the later ones.
Jesung Yang 4 months ago
parent ec884b3 · commit 2619bd2
-rw-r--r--crates/hir/src/semantics.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/incorrect_case.rs3
-rw-r--r--crates/ide-diagnostics/src/handlers/unused_variables.rs55
-rw-r--r--crates/ide-diagnostics/src/lib.rs10
4 files changed, 60 insertions, 10 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index ffb518b1e6..b15e642daa 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -267,7 +267,7 @@ impl<DB: HirDatabase + ?Sized> Semantics<'_, DB> {
&self,
krate: Crate,
item: ast::AnyHasAttrs,
- ) -> impl Iterator<Item = (LintAttr, SmolStr)> {
+ ) -> impl DoubleEndedIterator<Item = (LintAttr, SmolStr)> {
let mut cfg_options = None;
let cfg_options = || *cfg_options.get_or_insert_with(|| krate.id.cfg_options(self.db));
let mut result = Vec::new();
diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index fdc426c32c..4a12c5a26d 100644
--- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -1000,7 +1000,8 @@ mod OtherBadCase;
// ^^^^^^^^^^^^ 💡 error: Module `OtherBadCase` should have snake_case name, e.g. `other_bad_case`
//- /BAD_CASE/OtherBadCase.rs
-#![deny(non_snake_case)]
+#![allow(non_snake_case)]
+#![deny(non_snake_case)] // The lint level has been overridden.
fn FOO() {}
// ^^^ 💡 error: Function `FOO` should have snake_case name, e.g. `foo`
diff --git a/crates/ide-diagnostics/src/handlers/unused_variables.rs b/crates/ide-diagnostics/src/handlers/unused_variables.rs
index 84e63acbc0..b7ec8fa53f 100644
--- a/crates/ide-diagnostics/src/handlers/unused_variables.rs
+++ b/crates/ide-diagnostics/src/handlers/unused_variables.rs
@@ -183,6 +183,61 @@ fn main2() {
}
#[test]
+ fn apply_last_lint_attribute_when_multiple_are_present() {
+ check_diagnostics(
+ r#"
+#![allow(unused_variables)]
+#![warn(unused_variables)]
+#![deny(unused_variables)]
+
+fn main() {
+ let x = 2;
+ //^ 💡 error: unused variable
+
+ #[deny(unused_variables)]
+ #[warn(unused_variables)]
+ #[allow(unused_variables)]
+ let y = 0;
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn prefer_closest_ancestor_lint_attribute() {
+ check_diagnostics(
+ r#"
+#![allow(unused_variables)]
+
+fn main() {
+ #![warn(unused_variables)]
+
+ #[deny(unused_variables)]
+ let x = 2;
+ //^ 💡 error: unused variable
+}
+
+#[warn(unused_variables)]
+fn main2() {
+ #[deny(unused_variables)]
+ let x = 2;
+ //^ 💡 error: unused variable
+}
+
+#[warn(unused_variables)]
+fn main3() {
+ let x = 2;
+ //^ 💡 warn: unused variable
+}
+
+fn main4() {
+ let x = 2;
+}
+"#,
+ );
+ }
+
+ #[test]
fn fix_unused_variable() {
check_fix(
r#"
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index fe04bd175c..343c28e8f9 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -643,19 +643,13 @@ fn find_outline_mod_lint_severity(
let mod_def = sema.to_module_def(&mod_node)?;
let module_source_file = sema.module_definition_node(mod_def);
- let mut result = None;
let lint_groups = lint_groups(&diag.code, edition);
lint_attrs(
sema,
krate,
ast::AnyHasAttrs::cast(module_source_file.value).expect("SourceFile always has attrs"),
)
- .for_each(|(lint, severity)| {
- if lint_groups.contains(&lint) {
- result = Some(severity);
- }
- });
- result
+ .find_map(|(lint, severity)| lint_groups.contains(&lint).then_some(severity))
}
fn lint_severity_at(
@@ -682,7 +676,7 @@ fn lint_attrs(
krate: hir::Crate,
ancestor: ast::AnyHasAttrs,
) -> impl Iterator<Item = (SmolStr, Severity)> {
- sema.lint_attrs(krate, ancestor).map(|(lint_attr, lint)| {
+ sema.lint_attrs(krate, ancestor).rev().map(|(lint_attr, lint)| {
let severity = match lint_attr {
hir::LintAttr::Allow | hir::LintAttr::Expect => Severity::Allow,
hir::LintAttr::Warn => Severity::Warning,