diff --git a/compiler/rustc_hir/src/attrs/mod.rs b/compiler/rustc_hir/src/attrs/mod.rs index 92dd77e80a51..fc064fa65af9 100644 --- a/compiler/rustc_hir/src/attrs/mod.rs +++ b/compiler/rustc_hir/src/attrs/mod.rs @@ -77,8 +77,11 @@ macro_rules! find_attr { rustc_hir::Attribute::Parsed($pattern) $(if $guard)? => { break 'done Some($e); } - // FIXME: doesn't actually trigger in other crates :/ - // https://github.com/rust-lang/rust/issues/110613 + rustc_hir::Attribute::Unparsed(..) => {} + // In lint emitting, there's a specific exception for this warning. + // It's not usually emitted from inside macros from other crates + // (see https://github.com/rust-lang/rust/issues/110613) + // But this one is! #[deny(unreachable_patterns)] _ => {} } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index e4715f6e2c10..f039799c3b7b 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -9,7 +9,7 @@ use rustc_session::Session; use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS}; use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId}; -use rustc_span::{DUMMY_SP, Span, Symbol, kw}; +use rustc_span::{DUMMY_SP, ExpnKind, Span, Symbol, kw}; use tracing::instrument; use crate::ty::TyCtxt; @@ -380,7 +380,17 @@ fn lint_level_impl( // allow individual lints to opt-out from being reported. let incompatible = future_incompatible.is_some_and(|f| f.reason.edition().is_none()); - if !incompatible && !lint.report_in_external_macro { + // In rustc, for the find_attr macro, we want to always emit this. + // This completely circumvents normal lint checking, which usually doesn't happen for macros from other crates. + // However, we kind of want that when using find_attr from another rustc crate. So we cheat a little. + let is_in_find_attr = sess.enable_internal_lints() + && err.span.primary_spans().iter().any(|s| { + s.source_callee().is_some_and( + |i| matches!(i.kind, ExpnKind::Macro(_, name) if name.as_str() == "find_attr") + ) + }); + + if !incompatible && !lint.report_in_external_macro && !is_in_find_attr { err.cancel(); // Don't continue further, since we don't want to have diff --git a/tests/ui-fulldeps/internal-lints/find_attr.rs b/tests/ui-fulldeps/internal-lints/find_attr.rs index 00838132226f..bb0c8c486bcd 100644 --- a/tests/ui-fulldeps/internal-lints/find_attr.rs +++ b/tests/ui-fulldeps/internal-lints/find_attr.rs @@ -21,4 +21,7 @@ fn main() { //~^ ERROR use of `AttributeKind` in `find_attr!(...)` invocation find_attr!(attrs, AttributeKind::Inline(..) if true => todo!()); //~^ ERROR use of `AttributeKind` in `find_attr!(...)` invocation + + find_attr!(attrs, wildcard); + //~^ ERROR unreachable pattern } diff --git a/tests/ui-fulldeps/internal-lints/find_attr.stderr b/tests/ui-fulldeps/internal-lints/find_attr.stderr index 22c61563af70..ea8accaddb60 100644 --- a/tests/ui-fulldeps/internal-lints/find_attr.stderr +++ b/tests/ui-fulldeps/internal-lints/find_attr.stderr @@ -48,5 +48,27 @@ LL | find_attr!(attrs, AttributeKind::Inline(..) if true => todo!()); = note: `find_attr!(...)` already imports `AttributeKind::*` = help: remote `AttributeKind` -error: aborting due to 5 previous errors +error: unreachable pattern + --> $DIR/find_attr.rs:25:5 + | +LL | find_attr!(attrs, wildcard); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this + | +note: multiple earlier patterns match some of the same values + --> $DIR/find_attr.rs:25:5 + | +LL | find_attr!(attrs, wildcard); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | matches some of the same values + | matches some of the same values + | collectively making this unreachable +note: the lint level is defined here + --> $DIR/find_attr.rs:25:5 + | +LL | find_attr!(attrs, wildcard); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::find_attr` which comes from the expansion of the macro `find_attr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors