Skip to content

Commit 2619bd2

Browse files
committed
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.
1 parent ec884b3 commit 2619bd2

File tree

4 files changed

+60
-10
lines changed

4 files changed

+60
-10
lines changed

crates/hir/src/semantics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ impl<DB: HirDatabase + ?Sized> Semantics<'_, DB> {
267267
&self,
268268
krate: Crate,
269269
item: ast::AnyHasAttrs,
270-
) -> impl Iterator<Item = (LintAttr, SmolStr)> {
270+
) -> impl DoubleEndedIterator<Item = (LintAttr, SmolStr)> {
271271
let mut cfg_options = None;
272272
let cfg_options = || *cfg_options.get_or_insert_with(|| krate.id.cfg_options(self.db));
273273
let mut result = Vec::new();

crates/ide-diagnostics/src/handlers/incorrect_case.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,8 @@ mod OtherBadCase;
10001000
// ^^^^^^^^^^^^ 💡 error: Module `OtherBadCase` should have snake_case name, e.g. `other_bad_case`
10011001
10021002
//- /BAD_CASE/OtherBadCase.rs
1003-
#![deny(non_snake_case)]
1003+
#![allow(non_snake_case)]
1004+
#![deny(non_snake_case)] // The lint level has been overridden.
10041005
10051006
fn FOO() {}
10061007
// ^^^ 💡 error: Function `FOO` should have snake_case name, e.g. `foo`

crates/ide-diagnostics/src/handlers/unused_variables.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,61 @@ fn main2() {
182182
);
183183
}
184184

185+
#[test]
186+
fn apply_last_lint_attribute_when_multiple_are_present() {
187+
check_diagnostics(
188+
r#"
189+
#![allow(unused_variables)]
190+
#![warn(unused_variables)]
191+
#![deny(unused_variables)]
192+
193+
fn main() {
194+
let x = 2;
195+
//^ 💡 error: unused variable
196+
197+
#[deny(unused_variables)]
198+
#[warn(unused_variables)]
199+
#[allow(unused_variables)]
200+
let y = 0;
201+
}
202+
"#,
203+
);
204+
}
205+
206+
#[test]
207+
fn prefer_closest_ancestor_lint_attribute() {
208+
check_diagnostics(
209+
r#"
210+
#![allow(unused_variables)]
211+
212+
fn main() {
213+
#![warn(unused_variables)]
214+
215+
#[deny(unused_variables)]
216+
let x = 2;
217+
//^ 💡 error: unused variable
218+
}
219+
220+
#[warn(unused_variables)]
221+
fn main2() {
222+
#[deny(unused_variables)]
223+
let x = 2;
224+
//^ 💡 error: unused variable
225+
}
226+
227+
#[warn(unused_variables)]
228+
fn main3() {
229+
let x = 2;
230+
//^ 💡 warn: unused variable
231+
}
232+
233+
fn main4() {
234+
let x = 2;
235+
}
236+
"#,
237+
);
238+
}
239+
185240
#[test]
186241
fn fix_unused_variable() {
187242
check_fix(

crates/ide-diagnostics/src/lib.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -643,19 +643,13 @@ fn find_outline_mod_lint_severity(
643643

644644
let mod_def = sema.to_module_def(&mod_node)?;
645645
let module_source_file = sema.module_definition_node(mod_def);
646-
let mut result = None;
647646
let lint_groups = lint_groups(&diag.code, edition);
648647
lint_attrs(
649648
sema,
650649
krate,
651650
ast::AnyHasAttrs::cast(module_source_file.value).expect("SourceFile always has attrs"),
652651
)
653-
.for_each(|(lint, severity)| {
654-
if lint_groups.contains(&lint) {
655-
result = Some(severity);
656-
}
657-
});
658-
result
652+
.find_map(|(lint, severity)| lint_groups.contains(&lint).then_some(severity))
659653
}
660654

661655
fn lint_severity_at(
@@ -682,7 +676,7 @@ fn lint_attrs(
682676
krate: hir::Crate,
683677
ancestor: ast::AnyHasAttrs,
684678
) -> impl Iterator<Item = (SmolStr, Severity)> {
685-
sema.lint_attrs(krate, ancestor).map(|(lint_attr, lint)| {
679+
sema.lint_attrs(krate, ancestor).rev().map(|(lint_attr, lint)| {
686680
let severity = match lint_attr {
687681
hir::LintAttr::Allow | hir::LintAttr::Expect => Severity::Allow,
688682
hir::LintAttr::Warn => Severity::Warning,

0 commit comments

Comments
 (0)