diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index c26d7824758ef..6d451f3090acb 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -393,8 +393,14 @@ impl LateLintPass<'_> for Diagnostics { return; } + let mut found_parent_with_attr = false; let mut found_impl = false; - for (_, parent) in cx.tcx.hir().parent_iter(expr.hir_id) { + for (hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) { + if let Some(owner_did) = hir_id.as_owner() { + found_parent_with_attr = found_parent_with_attr + || cx.tcx.has_attr(owner_did.to_def_id(), sym::rustc_lint_diagnostics); + } + debug!(?parent); if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent && let Impl { of_trait: Some(of_trait), .. } = impl_ && @@ -407,7 +413,7 @@ impl LateLintPass<'_> for Diagnostics { } } debug!(?found_impl); - if !found_impl { + if !found_parent_with_attr && !found_impl { cx.struct_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, |lint| { lint.build(fluent::lint::diag_out_of_impl).emit(); }) @@ -425,7 +431,7 @@ impl LateLintPass<'_> for Diagnostics { } } debug!(?found_diagnostic_message); - if !found_diagnostic_message { + if !found_parent_with_attr && !found_diagnostic_message { cx.struct_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, |lint| { lint.build(fluent::lint::untranslatable_diag).emit(); }) diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs index 33192433bbf38..0e449256153a2 100644 --- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs +++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs @@ -1,6 +1,7 @@ // compile-flags: -Z unstable-options #![crate_type = "lib"] +#![feature(rustc_attrs)] #![feature(rustc_private)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -71,3 +72,10 @@ pub fn make_diagnostics<'a>(sess: &'a ParseSess) { //~^ ERROR diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls //~^^ ERROR diagnostics should be created using translatable messages } + +// Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted. + +#[rustc_lint_diagnostics] +pub fn skipped_because_of_annotation<'a>(sess: &'a ParseSess) { + let _diag = sess.struct_err("untranslatable diagnostic"); // okay! +} diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr index bae78ffdc021b..ed5105dabcd3f 100644 --- a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,41 +1,41 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:36:14 + --> $DIR/diagnostics.rs:37:14 | LL | sess.struct_err("untranslatable diagnostic") | ^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/diagnostics.rs:5:9 + --> $DIR/diagnostics.rs:6:9 | LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:53:14 + --> $DIR/diagnostics.rs:54:14 | LL | diag.note("untranslatable diagnostic"); | ^^^^ error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls - --> $DIR/diagnostics.rs:67:22 + --> $DIR/diagnostics.rs:68:22 | LL | let _diag = sess.struct_err(fluent::parser::expect_path); | ^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/diagnostics.rs:6:9 + --> $DIR/diagnostics.rs:7:9 | LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls - --> $DIR/diagnostics.rs:70:22 + --> $DIR/diagnostics.rs:71:22 | LL | let _diag = sess.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:70:22 + --> $DIR/diagnostics.rs:71:22 | LL | let _diag = sess.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^