Merge pull request #21265 from J3m3/lint-attr-order

fix: respect rustc's lint attribute application order
This commit is contained in:
Chayim Refael Friedman 2025-12-14 22:33:33 +00:00 committed by GitHub
commit 337b2d1d9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 10 deletions

View file

@ -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();

View file

@ -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`

View file

@ -182,6 +182,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(

View file

@ -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,