about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-03-20 20:02:18 +0100
committerCamille GILLOT <gillot.camille@gmail.com>2022-03-20 20:36:26 +0100
commit0b49d05ea33d68391e3d5472f3398d0ad1d9f9a6 (patch)
tree29a5bae15a0ce8bbc268c68c8e12a047a4481234
parent056951d6289e3fbba444cbadec8b4eea7f92928e (diff)
downloadrust-0b49d05ea33d68391e3d5472f3398d0ad1d9f9a6.tar.gz
rust-0b49d05ea33d68391e3d5472f3398d0ad1d9f9a6.zip
Filter OnceNote in diagnostic infra.
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs2
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs21
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs6
-rw-r--r--compiler/rustc_errors/src/lib.rs25
-rw-r--r--compiler/rustc_middle/src/lint.rs54
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs35
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs1
-rw-r--r--compiler/rustc_session/src/session.rs74
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs94
-rw-r--r--src/test/ui/autoref-autoderef/issue-38940.rs10
-rw-r--r--src/test/ui/autoref-autoderef/issue-38940.stderr4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr5
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr5
-rw-r--r--src/test/ui/did_you_mean/recursion_limit_deref.rs1
-rw-r--r--src/test/ui/did_you_mean/recursion_limit_deref.stderr4
-rw-r--r--src/test/ui/infinite/infinite-autoderef.rs3
-rw-r--r--src/test/ui/infinite/infinite-autoderef.stderr12
-rw-r--r--src/test/ui/issues/issue-33941.rs3
-rw-r--r--src/test/ui/issues/issue-33941.stderr16
-rw-r--r--src/test/ui/lint/issue-17718-const-naming.stderr5
-rw-r--r--src/test/ui/lint/lint-group-nonstandard-style.stderr10
-rw-r--r--src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr10
-rw-r--r--src/test/ui/liveness/liveness-consts.stderr5
-rw-r--r--src/test/ui/liveness/liveness-upvars.stderr5
-rw-r--r--src/test/ui/never_type/never-assign-dead-code.stderr5
-rw-r--r--src/test/ui/proc-macro/generate-mod.stderr8
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr4
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr3
29 files changed, 183 insertions, 282 deletions
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index c380455012d..5f59eba23f8 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -70,7 +70,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType {
             AnnotationType::Error
         }
         Level::Warning => AnnotationType::Warning,
-        Level::Note => AnnotationType::Note,
+        Level::Note | Level::OnceNote => AnnotationType::Note,
         Level::Help => AnnotationType::Help,
         // FIXME(#59346): Not sure how to map this level
         Level::FailureNote => AnnotationType::Error,
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 5c36c3c55b5..00ecbbbb93b 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -135,7 +135,12 @@ impl Diagnostic {
             | Level::Error { .. }
             | Level::FailureNote => true,
 
-            Level::Warning | Level::Note | Level::Help | Level::Allow | Level::Expect(_) => false,
+            Level::Warning
+            | Level::Note
+            | Level::OnceNote
+            | Level::Help
+            | Level::Allow
+            | Level::Expect(_) => false,
         }
     }
 
@@ -335,11 +340,25 @@ impl Diagnostic {
 
     /// Prints the span with a note above it.
     /// This is like [`Diagnostic::note()`], but it gets its own span.
+    pub fn note_once(&mut self, msg: &str) -> &mut Self {
+        self.sub(Level::OnceNote, msg, MultiSpan::new(), None);
+        self
+    }
+
+    /// Prints the span with a note above it.
+    /// This is like [`Diagnostic::note()`], but it gets its own span.
     pub fn span_note<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self {
         self.sub(Level::Note, msg, sp.into(), None);
         self
     }
 
+    /// Prints the span with a note above it.
+    /// This is like [`Diagnostic::note()`], but it gets its own span.
+    pub fn span_note_once<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self {
+        self.sub(Level::OnceNote, msg, sp.into(), None);
+        self
+    }
+
     /// Add a warning attached to this diagnostic.
     pub fn warn(&mut self, msg: &str) -> &mut Self {
         self.sub(Level::Warning, msg, MultiSpan::new(), None);
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 34236d36035..088f6091528 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -396,11 +396,17 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
     ) -> &mut Self);
 
     forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
+    forward!(pub fn note_once(&mut self, msg: &str) -> &mut Self);
     forward!(pub fn span_note(
         &mut self,
         sp: impl Into<MultiSpan>,
         msg: &str,
     ) -> &mut Self);
+    forward!(pub fn span_note_once(
+        &mut self,
+        sp: impl Into<MultiSpan>,
+        msg: &str,
+    ) -> &mut Self);
     forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
     forward!(pub fn span_warn(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> &mut Self);
     forward!(pub fn help(&mut self, msg: &str) -> &mut Self);
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 7cfb332d69d..2f2f6ed1a5a 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -4,6 +4,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
+#![feature(drain_filter)]
 #![feature(backtrace)]
 #![feature(if_let_guard)]
 #![feature(let_else)]
@@ -1070,7 +1071,23 @@ impl HandlerInner {
         // Only emit the diagnostic if we've been asked to deduplicate and
         // haven't already emitted an equivalent diagnostic.
         if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
-            self.emitter.emit_diagnostic(diagnostic);
+            debug!(?diagnostic);
+            debug!(?self.emitted_diagnostics);
+            let already_emitted_sub = |sub: &mut SubDiagnostic| {
+                debug!(?sub);
+                if sub.level != Level::OnceNote {
+                    return false;
+                }
+                let mut hasher = StableHasher::new();
+                sub.hash(&mut hasher);
+                let diagnostic_hash = hasher.finish();
+                debug!(?diagnostic_hash);
+                !self.emitted_diagnostics.insert(diagnostic_hash)
+            };
+
+            diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {});
+
+            self.emitter.emit_diagnostic(&diagnostic);
             if diagnostic.is_error() {
                 self.deduplicated_err_count += 1;
             } else if diagnostic.level == Warning {
@@ -1350,6 +1367,8 @@ pub enum Level {
     },
     Warning,
     Note,
+    /// A note that is only emitted once.
+    OnceNote,
     Help,
     FailureNote,
     Allow,
@@ -1372,7 +1391,7 @@ impl Level {
             Warning => {
                 spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows));
             }
-            Note => {
+            Note | OnceNote => {
                 spec.set_fg(Some(Color::Green)).set_intense(true);
             }
             Help => {
@@ -1389,7 +1408,7 @@ impl Level {
             Bug | DelayedBug => "error: internal compiler error",
             Fatal | Error { .. } => "error",
             Warning => "warning",
-            Note => "note",
+            Note | OnceNote => "note",
             Help => "help",
             FailureNote => "failure-note",
             Allow => panic!("Shouldn't call on allowed error"),
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index dc1fe5f2b08..1f0cd907f8a 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -12,7 +12,7 @@ use rustc_session::lint::{
     builtin::{self, FORBIDDEN_LINT_GROUPS},
     FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId,
 };
-use rustc_session::{DiagnosticMessageId, Session};
+use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
 use rustc_span::{symbol, Span, Symbol, DUMMY_SP};
@@ -245,7 +245,6 @@ impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
 }
 
 pub fn explain_lint_level_source(
-    sess: &Session,
     lint: &'static Lint,
     level: Level,
     src: LintLevelSource,
@@ -254,11 +253,7 @@ pub fn explain_lint_level_source(
     let name = lint.name_lower();
     match src {
         LintLevelSource::Default => {
-            sess.diag_note_once(
-                err,
-                DiagnosticMessageId::from(lint),
-                &format!("`#[{}({})]` on by default", level.as_str(), name),
-            );
+            err.note_once(&format!("`#[{}({})]` on by default", level.as_str(), name));
         }
         LintLevelSource::CommandLine(lint_flag_val, orig_level) => {
             let flag = match orig_level {
@@ -273,46 +268,29 @@ pub fn explain_lint_level_source(
             };
             let hyphen_case_lint_name = name.replace('_', "-");
             if lint_flag_val.as_str() == name {
-                sess.diag_note_once(
-                    err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "requested on the command line with `{} {}`",
-                        flag, hyphen_case_lint_name
-                    ),
-                );
+                err.note_once(&format!(
+                    "requested on the command line with `{} {}`",
+                    flag, hyphen_case_lint_name
+                ));
             } else {
                 let hyphen_case_flag_val = lint_flag_val.as_str().replace('_', "-");
-                sess.diag_note_once(
-                    err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "`{} {}` implied by `{} {}`",
-                        flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
-                    ),
-                );
+                err.note_once(&format!(
+                    "`{} {}` implied by `{} {}`",
+                    flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
+                ));
             }
         }
         LintLevelSource::Node(lint_attr_name, src, reason) => {
             if let Some(rationale) = reason {
                 err.note(rationale.as_str());
             }
-            sess.diag_span_note_once(
-                err,
-                DiagnosticMessageId::from(lint),
-                src,
-                "the lint level is defined here",
-            );
+            err.span_note_once(src, "the lint level is defined here");
             if lint_attr_name.as_str() != name {
                 let level_str = level.as_str();
-                sess.diag_note_once(
-                    err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "`#[{}({})]` implied by `#[{}({})]`",
-                        level_str, name, level_str, lint_attr_name
-                    ),
-                );
+                err.note_once(&format!(
+                    "`#[{}({})]` implied by `#[{}({})]`",
+                    level_str, name, level_str, lint_attr_name
+                ));
             }
         }
     }
@@ -412,7 +390,7 @@ pub fn struct_lint_level<'s, 'd>(
             return;
         }
 
-        explain_lint_level_source(sess, lint, level, src, &mut err);
+        explain_lint_level_source(lint, level, src, &mut err);
 
         let name = lint.name_lower();
         let is_force_warn = matches!(level, Level::ForceWarn);
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 219af6caa1a..fd6e241346d 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -17,9 +17,9 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
 use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer};
 use rustc_session::parse::feature_err_issue;
-use rustc_session::{DiagnosticMessageId, Session};
+use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{MultiSpan, Span};
+use rustc_span::Span;
 use std::num::NonZeroU32;
 
 #[derive(PartialEq, Clone, Copy, Debug)]
@@ -94,30 +94,15 @@ pub fn report_unstable(
         None => format!("use of unstable library feature '{}'", &feature),
     };
 
-    let msp: MultiSpan = span.into();
-    let sm = &sess.parse_sess.source_map();
-    let span_key = msp.primary_span().and_then(|sp: Span| {
-        if !sp.is_dummy() {
-            let file = sm.lookup_char_pos(sp.lo()).file;
-            if file.is_imported() { None } else { Some(span) }
-        } else {
-            None
-        }
-    });
-
-    let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone());
-    let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
-    if fresh {
-        if is_soft {
-            soft_handler(SOFT_UNSTABLE, span, &msg)
-        } else {
-            let mut err =
-                feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg);
-            if let Some((inner_types, ref msg, sugg, applicability)) = suggestion {
-                err.span_suggestion(inner_types, msg, sugg, applicability);
-            }
-            err.emit();
+    if is_soft {
+        soft_handler(SOFT_UNSTABLE, span, &msg)
+    } else {
+        let mut err =
+            feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg);
+        if let Some((inner_types, ref msg, sugg, applicability)) = suggestion {
+            err.span_suggestion(inner_types, msg, sugg, applicability);
         }
+        err.emit();
     }
 }
 
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index f8d0e448ce7..8de05990cdf 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -554,7 +554,6 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
                     tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, usage_lint_root);
                 assert_eq!(level, Level::Allow);
                 lint::explain_lint_level_source(
-                    tcx.sess,
                     UNSAFE_OP_IN_UNSAFE_FN,
                     Level::Allow,
                     source,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 7eeb6f90f99..4b2eea5c2cb 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -19,7 +19,7 @@ use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
 use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
 use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
-use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
+use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
 use rustc_macros::HashStable_Generic;
 pub use rustc_span::def_id::StableCrateId;
 use rustc_span::edition::Edition;
@@ -35,7 +35,6 @@ use std::cell::{self, RefCell};
 use std::env;
 use std::fmt;
 use std::io::Write;
-use std::num::NonZeroU32;
 use std::ops::{Div, Mul};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
@@ -136,10 +135,6 @@ pub struct Session {
     /// `None` means that there is no source file.
     pub local_crate_source_file: Option<PathBuf>,
 
-    /// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking
-    /// (sub)diagnostics that have been set once, but should not be set again,
-    /// in order to avoid redundantly verbose output (Issue #24690, #44953).
-    pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
     crate_types: OnceCell<Vec<CrateType>>,
     /// The `stable_crate_id` is constructed out of the crate name and all the
     /// `-C metadata` arguments passed to the compiler. Its value forms a unique
@@ -209,13 +204,6 @@ pub struct PerfStats {
     pub normalize_projection_ty: AtomicUsize,
 }
 
-/// Enum to support dispatch of one-time diagnostics (in `Session.diag_once`).
-enum DiagnosticBuilderMethod {
-    Note,
-    SpanNote,
-    // Add more variants as needed to support one-time diagnostics.
-}
-
 /// Trait implemented by error types. This should not be implemented manually. Instead, use
 /// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic].
 pub trait SessionDiagnostic<'a> {
@@ -224,21 +212,6 @@ pub trait SessionDiagnostic<'a> {
     fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, ErrorGuaranteed>;
 }
 
-/// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid
-/// emitting the same message more than once.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum DiagnosticMessageId {
-    ErrorId(u16), // EXXXX error code as integer
-    LintId(lint::LintId),
-    StabilityId(Option<NonZeroU32>), // issue number
-}
-
-impl From<&'static lint::Lint> for DiagnosticMessageId {
-    fn from(lint: &'static lint::Lint) -> Self {
-        DiagnosticMessageId::LintId(lint::LintId::of(lint))
-    }
-}
-
 impl Session {
     pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option<Symbol>) {
         self.miri_unleashed_features.lock().push((span, feature_gate));
@@ -497,50 +470,6 @@ impl Session {
         &self.parse_sess.span_diagnostic
     }
 
-    /// Analogous to calling methods on the given `DiagnosticBuilder`, but
-    /// deduplicates on lint ID, span (if any), and message for this `Session`
-    fn diag_once(
-        &self,
-        diag: &mut Diagnostic,
-        method: DiagnosticBuilderMethod,
-        msg_id: DiagnosticMessageId,
-        message: &str,
-        span_maybe: Option<Span>,
-    ) {
-        let id_span_message = (msg_id, span_maybe, message.to_owned());
-        let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message);
-        if fresh {
-            match method {
-                DiagnosticBuilderMethod::Note => {
-                    diag.note(message);
-                }
-                DiagnosticBuilderMethod::SpanNote => {
-                    let span = span_maybe.expect("`span_note` needs a span");
-                    diag.span_note(span, message);
-                }
-            }
-        }
-    }
-
-    pub fn diag_span_note_once(
-        &self,
-        diag: &mut Diagnostic,
-        msg_id: DiagnosticMessageId,
-        span: Span,
-        message: &str,
-    ) {
-        self.diag_once(diag, DiagnosticBuilderMethod::SpanNote, msg_id, message, Some(span));
-    }
-
-    pub fn diag_note_once(
-        &self,
-        diag: &mut Diagnostic,
-        msg_id: DiagnosticMessageId,
-        message: &str,
-    ) {
-        self.diag_once(diag, DiagnosticBuilderMethod::Note, msg_id, message, None);
-    }
-
     #[inline]
     pub fn source_map(&self) -> &SourceMap {
         self.parse_sess.source_map()
@@ -1306,7 +1235,6 @@ pub fn build_session(
         parse_sess,
         sysroot,
         local_crate_source_file,
-        one_time_diagnostics: Default::default(),
         crate_types: OnceCell::new(),
         stable_crate_id: OnceCell::new(),
         features: OnceCell::new(),
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index 46c74660f86..5b88cff03d7 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_trait_selection/src/autoderef.rs
@@ -5,7 +5,7 @@ use rustc_hir as hir;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
 use rustc_middle::ty::{ToPredicate, TypeFoldable};
-use rustc_session::{DiagnosticMessageId, Limit};
+use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Span;
 
@@ -222,24 +222,19 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa
         Limit(0) => Limit(2),
         limit => limit * 2,
     };
-    let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
-    let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
-    let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-    if fresh {
-        struct_span_err!(
-            tcx.sess,
-            span,
-            E0055,
-            "reached the recursion limit while auto-dereferencing `{:?}`",
-            ty
-        )
-        .span_label(span, "deref recursion limit reached")
-        .help(&format!(
-            "consider increasing the recursion limit by adding a \
+    struct_span_err!(
+        tcx.sess,
+        span,
+        E0055,
+        "reached the recursion limit while auto-dereferencing `{:?}`",
+        ty
+    )
+    .span_label(span, "deref recursion limit reached")
+    .help(&format!(
+        "consider increasing the recursion limit by adding a \
              `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
-            suggested_limit,
-            tcx.crate_name(LOCAL_CRATE),
-        ))
-        .emit();
-    }
+        suggested_limit,
+        tcx.crate_name(LOCAL_CRATE),
+    ))
+    .emit();
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 229e108d5d6..e32d5142090 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -27,7 +27,6 @@ use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable,
 };
-use rustc_session::DiagnosticMessageId;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
 use std::fmt;
@@ -1401,60 +1400,49 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 }
             }
 
-            let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
-            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-            if fresh {
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    obligation.cause.span,
-                    E0271,
-                    "type mismatch resolving `{}`",
-                    predicate
-                );
-                let secondary_span = match predicate.kind().skip_binder() {
-                    ty::PredicateKind::Projection(proj) => self
-                        .tcx
-                        .opt_associated_item(proj.projection_ty.item_def_id)
-                        .and_then(|trait_assoc_item| {
+            let mut diag = struct_span_err!(
+                self.tcx.sess,
+                obligation.cause.span,
+                E0271,
+                "type mismatch resolving `{}`",
+                predicate
+            );
+            let secondary_span = match predicate.kind().skip_binder() {
+                ty::PredicateKind::Projection(proj) => self
+                    .tcx
+                    .opt_associated_item(proj.projection_ty.item_def_id)
+                    .and_then(|trait_assoc_item| {
+                        self.tcx
+                            .trait_of_item(proj.projection_ty.item_def_id)
+                            .map(|id| (trait_assoc_item, id))
+                    })
+                    .and_then(|(trait_assoc_item, id)| {
+                        let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
+                        self.tcx.find_map_relevant_impl(id, proj.projection_ty.self_ty(), |did| {
                             self.tcx
-                                .trait_of_item(proj.projection_ty.item_def_id)
-                                .map(|id| (trait_assoc_item, id))
-                        })
-                        .and_then(|(trait_assoc_item, id)| {
-                            let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
-                            self.tcx.find_map_relevant_impl(
-                                id,
-                                proj.projection_ty.self_ty(),
-                                |did| {
-                                    self.tcx
-                                        .associated_items(did)
-                                        .in_definition_order()
-                                        .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
-                                },
-                            )
+                                .associated_items(did)
+                                .in_definition_order()
+                                .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
                         })
-                        .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
-                            Some(
-                                hir::Node::TraitItem(hir::TraitItem {
-                                    kind: hir::TraitItemKind::Type(_, Some(ty)),
-                                    ..
-                                })
-                                | hir::Node::ImplItem(hir::ImplItem {
-                                    kind: hir::ImplItemKind::TyAlias(ty),
-                                    ..
-                                }),
-                            ) => {
-                                Some((ty.span, format!("type mismatch resolving `{}`", predicate)))
-                            }
-                            _ => None,
-                        }),
-                    _ => None,
-                };
-                self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
-                self.note_obligation_cause(&mut diag, obligation);
-                diag.emit();
-            }
+                    })
+                    .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
+                        Some(
+                            hir::Node::TraitItem(hir::TraitItem {
+                                kind: hir::TraitItemKind::Type(_, Some(ty)),
+                                ..
+                            })
+                            | hir::Node::ImplItem(hir::ImplItem {
+                                kind: hir::ImplItemKind::TyAlias(ty),
+                                ..
+                            }),
+                        ) => Some((ty.span, format!("type mismatch resolving `{}`", predicate))),
+                        _ => None,
+                    }),
+                _ => None,
+            };
+            self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
+            self.note_obligation_cause(&mut diag, obligation);
+            diag.emit();
         });
     }
 
diff --git a/src/test/ui/autoref-autoderef/issue-38940.rs b/src/test/ui/autoref-autoderef/issue-38940.rs
index 3f10fc017a7..d2f1c6e3271 100644
--- a/src/test/ui/autoref-autoderef/issue-38940.rs
+++ b/src/test/ui/autoref-autoderef/issue-38940.rs
@@ -2,8 +2,10 @@
 // Test that the recursion limit can be changed. In this case, we have
 // deeply nested types that will fail the `Send` check by overflow
 // when the recursion limit is set very low.
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![allow(dead_code)]
-#![recursion_limit="10"]
+#![recursion_limit = "10"]
 macro_rules! link {
     ($outer:ident, $inner:ident) => {
         struct $outer($inner);
@@ -18,14 +20,17 @@ macro_rules! link {
                 &self.0
             }
         }
-    }
+    };
 }
+
 struct Bottom;
+
 impl Bottom {
     fn new() -> Bottom {
         Bottom
     }
 }
+
 link!(Top, A);
 link!(A, B);
 link!(B, C);
@@ -38,6 +43,7 @@ link!(H, I);
 link!(I, J);
 link!(J, K);
 link!(K, Bottom);
+
 fn main() {
     let t = Top::new();
     let x: &Bottom = &t;
diff --git a/src/test/ui/autoref-autoderef/issue-38940.stderr b/src/test/ui/autoref-autoderef/issue-38940.stderr
index a560334314c..f0b8405770e 100644
--- a/src/test/ui/autoref-autoderef/issue-38940.stderr
+++ b/src/test/ui/autoref-autoderef/issue-38940.stderr
@@ -1,5 +1,5 @@
 error[E0055]: reached the recursion limit while auto-dereferencing `J`
-  --> $DIR/issue-38940.rs:43:22
+  --> $DIR/issue-38940.rs:49:22
    |
 LL |     let x: &Bottom = &t;
    |                      ^^ deref recursion limit reached
@@ -7,7 +7,7 @@ LL |     let x: &Bottom = &t;
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`issue_38940`)
 
 error[E0308]: mismatched types
-  --> $DIR/issue-38940.rs:43:22
+  --> $DIR/issue-38940.rs:49:22
    |
 LL |     let x: &Bottom = &t;
    |            -------   ^^ expected struct `Bottom`, found struct `Top`
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
index 74109772724..7e767cba3cc 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
@@ -18,11 +18,6 @@ warning: unused variable: `a`
 LL |         a += 1;
    |         ^
    |
-note: the lint level is defined here
-  --> $DIR/liveness.rs:5:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
    = help: did you mean to capture by reference instead?
 
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
index 11a440554f7..2ac801b49f1 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
@@ -18,11 +18,6 @@ warning: unused variable: `a`
 LL |         a = s;
    |         ^
    |
-note: the lint level is defined here
-  --> $DIR/liveness_unintentional_copy.rs:4:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
    = help: did you mean to capture by reference instead?
 
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.rs b/src/test/ui/did_you_mean/recursion_limit_deref.rs
index 613843801d4..41bbca661dd 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.rs
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.rs
@@ -1,6 +1,7 @@
 // Test that the recursion limit can be changed and that the compiler
 // suggests a fix. In this case, we have a long chain of Deref impls
 // which will cause an overflow during the autoderef loop.
+// compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![allow(dead_code)]
 #![recursion_limit="10"]
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
index 658207a47c9..a6b5681a68c 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
@@ -1,5 +1,5 @@
 error[E0055]: reached the recursion limit while auto-dereferencing `J`
-  --> $DIR/recursion_limit_deref.rs:50:22
+  --> $DIR/recursion_limit_deref.rs:51:22
    |
 LL |     let x: &Bottom = &t;
    |                      ^^ deref recursion limit reached
@@ -7,7 +7,7 @@ LL |     let x: &Bottom = &t;
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_deref`)
 
 error[E0308]: mismatched types
-  --> $DIR/recursion_limit_deref.rs:50:22
+  --> $DIR/recursion_limit_deref.rs:51:22
    |
 LL |     let x: &Bottom = &t;
    |            -------   ^^ expected struct `Bottom`, found struct `Top`
diff --git a/src/test/ui/infinite/infinite-autoderef.rs b/src/test/ui/infinite/infinite-autoderef.rs
index ca26252832b..cbbe1f81df8 100644
--- a/src/test/ui/infinite/infinite-autoderef.rs
+++ b/src/test/ui/infinite/infinite-autoderef.rs
@@ -1,6 +1,5 @@
 // error-pattern: reached the recursion limit while auto-dereferencing
-
-
+// compile-flags: -Zdeduplicate-diagnostics=yes
 
 use std::ops::Deref;
 
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
index 2d29f0592e1..2e950dbb8c7 100644
--- a/src/test/ui/infinite/infinite-autoderef.stderr
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/infinite-autoderef.rs:20:13
+  --> $DIR/infinite-autoderef.rs:19:13
    |
 LL |         x = Box::new(x);
    |             ^^^^^^^^^^^ cyclic type of infinite size
@@ -10,7 +10,7 @@ LL |         x = *Box::new(x);
    |             +
 
 error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
-  --> $DIR/infinite-autoderef.rs:25:5
+  --> $DIR/infinite-autoderef.rs:24:5
    |
 LL |     Foo.foo;
    |     ^^^^^^^ deref recursion limit reached
@@ -18,7 +18,7 @@ LL |     Foo.foo;
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
-  --> $DIR/infinite-autoderef.rs:25:9
+  --> $DIR/infinite-autoderef.rs:24:9
    |
 LL |     Foo.foo;
    |         ^^^ deref recursion limit reached
@@ -26,13 +26,13 @@ LL |     Foo.foo;
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0609]: no field `foo` on type `Foo`
-  --> $DIR/infinite-autoderef.rs:25:9
+  --> $DIR/infinite-autoderef.rs:24:9
    |
 LL |     Foo.foo;
    |         ^^^ unknown field
 
 error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
-  --> $DIR/infinite-autoderef.rs:26:9
+  --> $DIR/infinite-autoderef.rs:25:9
    |
 LL |     Foo.bar();
    |         ^^^ deref recursion limit reached
@@ -40,7 +40,7 @@ LL |     Foo.bar();
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0599]: no method named `bar` found for struct `Foo` in the current scope
-  --> $DIR/infinite-autoderef.rs:26:9
+  --> $DIR/infinite-autoderef.rs:25:9
    |
 LL | struct Foo;
    | ----------- method `bar` not found for this
diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs
index ccaa6334856..a1213623e6f 100644
--- a/src/test/ui/issues/issue-33941.rs
+++ b/src/test/ui/issues/issue-33941.rs
@@ -1,6 +1,9 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
 use std::collections::HashMap;
 
 fn main() {
     for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
     //~^ ERROR type mismatch
+    //~| ERROR type mismatch
 }
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
index c6650d60c21..e1ce6eed98e 100644
--- a/src/test/ui/issues/issue-33941.stderr
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
-  --> $DIR/issue-33941.rs:4:36
+  --> $DIR/issue-33941.rs:6:36
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
    |                                    ^^^^^^ expected reference, found tuple
@@ -13,7 +13,7 @@ LL |         Self: Sized + Iterator<Item = &'a T>,
    |                                ^^^^^^^^^^^^ required by this bound in `cloned`
 
 error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
-  --> $DIR/issue-33941.rs:4:14
+  --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
@@ -23,6 +23,16 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
    = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
 
-error: aborting due to 2 previous errors
+error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
+  --> $DIR/issue-33941.rs:6:14
+   |
+LL |     for _ in HashMap::new().iter().cloned() {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+   |
+   = note:  expected tuple `(&_, &_)`
+           found reference `&_`
+   = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr
index ce4ebcb5e3e..a1fc99c9a3d 100644
--- a/src/test/ui/lint/issue-17718-const-naming.stderr
+++ b/src/test/ui/lint/issue-17718-const-naming.stderr
@@ -17,11 +17,6 @@ error: constant `foo` should have an upper case name
 LL | const foo: isize = 3;
    |       ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO`
    |
-note: the lint level is defined here
-  --> $DIR/issue-17718-const-naming.rs:2:9
-   |
-LL | #![deny(warnings)]
-   |         ^^^^^^^^
    = note: `#[deny(non_upper_case_globals)]` implied by `#[deny(warnings)]`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr
index 0ce33090f66..fcd01012371 100644
--- a/src/test/ui/lint/lint-group-nonstandard-style.stderr
+++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr
@@ -43,11 +43,6 @@ error: static variable `bad` should have an upper case name
 LL |         static bad: isize = 1;
    |                ^^^ help: convert the identifier to upper case: `BAD`
    |
-note: the lint level is defined here
-  --> $DIR/lint-group-nonstandard-style.rs:10:14
-   |
-LL |     #[forbid(nonstandard_style)]
-   |              ^^^^^^^^^^^^^^^^^
    = note: `#[forbid(non_upper_case_globals)]` implied by `#[forbid(nonstandard_style)]`
 
 warning: function `CamelCase` should have a snake case name
@@ -56,11 +51,6 @@ warning: function `CamelCase` should have a snake case name
 LL |         fn CamelCase() {}
    |            ^^^^^^^^^ help: convert the identifier to snake case: `camel_case`
    |
-note: the lint level is defined here
-  --> $DIR/lint-group-nonstandard-style.rs:18:17
-   |
-LL |         #![warn(nonstandard_style)]
-   |                 ^^^^^^^^^^^^^^^^^
    = note: `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]`
 
 error: aborting due to 3 previous errors; 2 warnings emitted
diff --git a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
index 2ef655efdbd..26fa6eb9b9b 100644
--- a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -49,11 +49,6 @@ warning: value assigned to `hours_are_suns` is never read
 LL |         hours_are_suns = false;
    |         ^^^^^^^^^^^^^^
    |
-note: the lint level is defined here
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
-   |
-LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
-   |         ^^^^^^
    = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
    = help: maybe it is overwritten before being read?
 
@@ -107,11 +102,6 @@ LL |     let mut mut_unused_var = 1;
    |         |
    |         help: remove this `mut`
    |
-note: the lint level is defined here
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
-   |
-LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
-   |         ^^^^^^
    = note: `#[warn(unused_mut)]` implied by `#[warn(unused)]`
 
 warning: variable does not need to be mutable
diff --git a/src/test/ui/liveness/liveness-consts.stderr b/src/test/ui/liveness/liveness-consts.stderr
index b1beec97df5..adaf5431629 100644
--- a/src/test/ui/liveness/liveness-consts.stderr
+++ b/src/test/ui/liveness/liveness-consts.stderr
@@ -18,11 +18,6 @@ warning: value assigned to `b` is never read
 LL |     b += 1;
    |     ^
    |
-note: the lint level is defined here
-  --> $DIR/liveness-consts.rs:2:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
    = help: maybe it is overwritten before being read?
 
diff --git a/src/test/ui/liveness/liveness-upvars.stderr b/src/test/ui/liveness/liveness-upvars.stderr
index d1723302513..cb104e0a3fd 100644
--- a/src/test/ui/liveness/liveness-upvars.stderr
+++ b/src/test/ui/liveness/liveness-upvars.stderr
@@ -18,11 +18,6 @@ warning: unused variable: `last`
 LL |         last = Some(s);
    |         ^^^^
    |
-note: the lint level is defined here
-  --> $DIR/liveness-upvars.rs:4:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
    = help: did you mean to capture by reference instead?
 
diff --git a/src/test/ui/never_type/never-assign-dead-code.stderr b/src/test/ui/never_type/never-assign-dead-code.stderr
index 5c5cafadc85..521b82023c9 100644
--- a/src/test/ui/never_type/never-assign-dead-code.stderr
+++ b/src/test/ui/never_type/never-assign-dead-code.stderr
@@ -27,11 +27,6 @@ warning: unused variable: `x`
 LL |     let x: ! = panic!("aah");
    |         ^ help: if this is intentional, prefix it with an underscore: `_x`
    |
-note: the lint level is defined here
-  --> $DIR/never-assign-dead-code.rs:6:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
 warning: 3 warnings emitted
diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr
index a2c1b82b15f..f1a167e37b4 100644
--- a/src/test/ui/proc-macro/generate-mod.stderr
+++ b/src/test/ui/proc-macro/generate-mod.stderr
@@ -101,6 +101,7 @@ error: cannot find type `OuterDerive` in this scope
 LL | #[derive(generate_mod::CheckDerive)]
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
+   = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
    = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -112,6 +113,7 @@ error: cannot find type `FromOutside` in this scope
 LL |     #[derive(generate_mod::CheckDerive)]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
+   = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
    = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -123,6 +125,7 @@ error: cannot find type `OuterDerive` in this scope
 LL |     #[derive(generate_mod::CheckDerive)]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
+   = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
    = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -150,6 +153,11 @@ warning: cannot find type `OuterDeriveLint` in this scope
 LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
+note: the lint level is defined here
+  --> $DIR/generate-mod.rs:30:10
+   |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
    = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
index bd9ba6a09fc..acba357b0d3 100644
--- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
+++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
@@ -111,6 +111,7 @@ LL |         #[my_macro] struct One($name);
 LL |     impl_macros!(Foo);
    |     ----------------- in this macro invocation
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
@@ -128,6 +129,7 @@ LL |         #[my_macro] struct Two($name);
 LL |     arrays!(Foo);
    |     ------------ in this macro invocation
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above
@@ -145,6 +147,7 @@ LL |         #[my_macro] struct Three($T);
 LL |     tuple_from_req!(Foo);
    |     -------------------- in this macro invocation
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
@@ -162,6 +165,7 @@ LL |         #[my_macro] struct Three($T);
 LL |     tuple_from_req!(Foo);
    |     -------------------- in this macro invocation
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
index 554613be65a..be4239089e8 100644
--- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
@@ -60,6 +60,7 @@ error: using `procedural-masquerade` crate
 LL | enum ProceduralMasqueradeDummyType {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
@@ -71,6 +72,7 @@ error: using `procedural-masquerade` crate
 LL | enum ProceduralMasqueradeDummyType {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
@@ -82,6 +84,7 @@ error: using `procedural-masquerade` crate
 LL | enum ProceduralMasqueradeDummyType {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.