From 0b49d05ea33d68391e3d5472f3398d0ad1d9f9a6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 20 Mar 2022 20:02:18 +0100 Subject: [PATCH] Filter OnceNote in diagnostic infra. --- .../src/annotate_snippet_emitter_writer.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 21 ++++- .../rustc_errors/src/diagnostic_builder.rs | 6 ++ compiler/rustc_errors/src/lib.rs | 25 ++++- compiler/rustc_middle/src/lint.rs | 54 ++++------- compiler/rustc_middle/src/middle/stability.rs | 35 ++----- .../rustc_mir_transform/src/check_unsafety.rs | 1 - compiler/rustc_session/src/session.rs | 74 +-------------- .../rustc_trait_selection/src/autoderef.rs | 35 +++---- .../src/traits/error_reporting/mod.rs | 94 ++++++++----------- src/test/ui/autoref-autoderef/issue-38940.rs | 10 +- .../ui/autoref-autoderef/issue-38940.stderr | 4 +- .../diagnostics/liveness.stderr | 5 - .../liveness_unintentional_copy.stderr | 5 - .../ui/did_you_mean/recursion_limit_deref.rs | 1 + .../did_you_mean/recursion_limit_deref.stderr | 4 +- src/test/ui/infinite/infinite-autoderef.rs | 3 +- .../ui/infinite/infinite-autoderef.stderr | 12 +-- src/test/ui/issues/issue-33941.rs | 3 + src/test/ui/issues/issue-33941.stderr | 16 +++- .../ui/lint/issue-17718-const-naming.stderr | 5 - .../lint/lint-group-nonstandard-style.stderr | 10 -- ...0-unused-variable-in-struct-pattern.stderr | 10 -- src/test/ui/liveness/liveness-consts.stderr | 5 - src/test/ui/liveness/liveness-upvars.stderr | 5 - .../never_type/never-assign-dead-code.stderr | 5 - src/test/ui/proc-macro/generate-mod.stderr | 8 ++ .../group-compat-hack.stderr | 4 + .../issue-73933-procedural-masquerade.stderr | 3 + 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, } } @@ -333,6 +338,13 @@ impl Diagnostic { self } + /// 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>(&mut self, sp: S, msg: &str) -> &mut Self { @@ -340,6 +352,13 @@ impl Diagnostic { 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>(&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, msg: &str, ) -> &mut Self); + forward!(pub fn span_note_once( + &mut self, + sp: impl Into, + msg: &str, + ) -> &mut Self); forward!(pub fn warn(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_warn(&mut self, sp: impl Into, 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, - /// Set of `(DiagnosticId, Option, 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, String)>>, crate_types: OnceCell>, /// 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), // 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) { 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, - ) { - 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)) + .associated_items(did) + .in_definition_order() + .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident) }) - .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) - }, - ) - }) - .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 ` 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, | ^^^^^^^^^^^^ required by this bound in `cloned` error[E0271]: type mismatch resolving ` 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>` = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` -error: aborting due to 2 previous errors +error[E0271]: type mismatch resolving ` 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>` + +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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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.