Skip to content

Commit 63cf6fe

Browse files
committed
Auto merge of rust-lang#18128 - ChayimFriedman2:external-macros-lint, r=Veykril
fix: Handle errors and lints from external macros Some lints should not be reported if they originate from an external macro, and quickfixes should be disabled (or they'll change library code). Fixes rust-lang#18122. Closes rust-lang#18124.
2 parents 3ffeee3 + fde01e9 commit 63cf6fe

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,23 @@ mod F {
369369
);
370370
}
371371

372+
#[test]
373+
fn external_macro() {
374+
check_diagnostics(
375+
r#"
376+
//- /library.rs library crate:library
377+
#[macro_export]
378+
macro_rules! trigger_lint {
379+
() => { let FOO: () };
380+
}
381+
//- /user.rs crate:user deps:library
382+
fn foo() {
383+
library::trigger_lint!();
384+
}
385+
"#,
386+
);
387+
}
388+
372389
#[test]
373390
fn complex_ignore() {
374391
check_diagnostics(

src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ mod tests;
7878

7979
use std::{collections::hash_map, sync::LazyLock};
8080

81-
use hir::{diagnostics::AnyDiagnostic, HirFileId, InFile, Semantics};
81+
use hir::{db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, HirFileId, InFile, Semantics};
8282
use ide_db::{
8383
assists::{Assist, AssistId, AssistKind, AssistResolveStrategy},
8484
base_db::SourceDatabase,
@@ -501,6 +501,17 @@ pub fn semantic_diagnostics(
501501

502502
res.retain(|d| d.severity != Severity::Allow);
503503

504+
res.retain_mut(|diag| {
505+
if let Some(node) = diag
506+
.main_node
507+
.map(|ptr| ptr.map(|node| node.to_node(&ctx.sema.parse_or_expand(ptr.file_id))))
508+
{
509+
handle_diag_from_macros(&ctx.sema, diag, &node)
510+
} else {
511+
true
512+
}
513+
});
514+
504515
res
505516
}
506517

@@ -517,6 +528,35 @@ pub fn full_diagnostics(
517528
res
518529
}
519530

531+
/// Returns whether to keep this diagnostic (or remove it).
532+
fn handle_diag_from_macros(
533+
sema: &Semantics<'_, RootDatabase>,
534+
diag: &mut Diagnostic,
535+
node: &InFile<SyntaxNode>,
536+
) -> bool {
537+
let Some(macro_file) = node.file_id.macro_file() else { return true };
538+
let span_map = sema.db.expansion_span_map(macro_file);
539+
let mut spans = span_map.spans_for_range(node.text_range());
540+
if spans.any(|span| {
541+
sema.db.lookup_intern_syntax_context(span.ctx).outer_expn.is_some_and(|expansion| {
542+
let macro_call =
543+
sema.db.lookup_intern_macro_call(expansion.as_macro_file().macro_call_id);
544+
!Crate::from(macro_call.def.krate).origin(sema.db).is_local()
545+
})
546+
}) {
547+
// Disable suggestions for external macros, they'll change library code and it's just bad.
548+
diag.fixes = None;
549+
550+
// All Clippy lints report in macros, see https://github.com/rust-lang/rust-clippy/blob/903293b199364/declare_clippy_lint/src/lib.rs#L172.
551+
if let DiagnosticCode::RustcLint(lint) = diag.code {
552+
if !LINTS_TO_REPORT_IN_EXTERNAL_MACROS.contains(lint) {
553+
return false;
554+
}
555+
};
556+
}
557+
true
558+
}
559+
520560
// `__RA_EVERY_LINT` is a fake lint group to allow every lint in proc macros
521561

522562
static RUSTC_LINT_GROUPS_DICT: LazyLock<FxHashMap<&str, Vec<&str>>> =
@@ -525,6 +565,10 @@ static RUSTC_LINT_GROUPS_DICT: LazyLock<FxHashMap<&str, Vec<&str>>> =
525565
static CLIPPY_LINT_GROUPS_DICT: LazyLock<FxHashMap<&str, Vec<&str>>> =
526566
LazyLock::new(|| build_group_dict(CLIPPY_LINT_GROUPS, &["__RA_EVERY_LINT"], "clippy::"));
527567

568+
// FIXME: Autogenerate this instead of enumerating by hand.
569+
static LINTS_TO_REPORT_IN_EXTERNAL_MACROS: LazyLock<FxHashSet<&str>> =
570+
LazyLock::new(|| FxHashSet::from_iter([]));
571+
528572
fn build_group_dict(
529573
lint_group: &'static [LintGroup],
530574
all_groups: &'static [&'static str],

0 commit comments

Comments
 (0)