diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 81d3d440b566f..eebf4d32ab26f 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -452,8 +452,7 @@ pub fn raw_struct_lint<'a>(sess: &'a Session, } if let Some(span) = def { - let explanation = "lint level defined here"; - err.span_note(span, &explanation); + sess.diag_span_note_once(&mut err, span, "lint level defined here"); } err diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index d002aba595bca..7917964c8f1b6 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -17,7 +17,7 @@ use middle::dependency_format; use session::search_paths::PathKind; use session::config::DebugInfoLevel; use ty::tls; -use util::nodemap::{NodeMap, FnvHashMap}; +use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet}; use util::common::duration_to_secs_str; use mir::transform as mir_pass; @@ -75,6 +75,10 @@ pub struct Session { pub working_dir: PathBuf, pub lint_store: RefCell, pub lints: RefCell>>, + /// Set of (span, message) tuples tracking lint (sub)diagnostics that have + /// been set once, but should not be set again, in order to avoid + /// redundantly verbose output (Issue #24690). + pub one_time_diagnostics: RefCell>, pub plugin_llvm_passes: RefCell>, pub mir_passes: RefCell, pub plugin_attributes: RefCell>, @@ -288,6 +292,26 @@ impl Session { pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { &self.parse_sess.span_diagnostic } + + /// Analogous to calling `.span_note` on the given DiagnosticBuilder, but + /// deduplicates on span and message for this `Session`. + // + // FIXME: if the need arises for one-time diagnostics other than + // `span_note`, we almost certainly want to generalize this "check the + // one-time diagnostics map, then set message if it's not already there" + // code to accomodate all of them + pub fn diag_span_note_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + span: Span, message: &str) { + let span_message = (span, message.to_owned()); + let already_noted: bool = self.one_time_diagnostics.borrow() + .contains(&span_message); + if !already_noted { + diag_builder.span_note(span, &message); + self.one_time_diagnostics.borrow_mut().insert(span_message); + } + } + pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { self.parse_sess.codemap() } @@ -561,6 +585,7 @@ pub fn build_session_(sopts: config::Options, working_dir: env::current_dir().unwrap(), lint_store: RefCell::new(lint::LintStore::new()), lints: RefCell::new(NodeMap()), + one_time_diagnostics: RefCell::new(FnvHashSet()), plugin_llvm_passes: RefCell::new(Vec::new()), mir_passes: RefCell::new(mir_pass::Passes::new()), plugin_attributes: RefCell::new(Vec::new()), diff --git a/src/test/compile-fail/lint-group-style.rs b/src/test/compile-fail/lint-group-style.rs index 393e46ab5394c..a88e0c63ac374 100644 --- a/src/test/compile-fail/lint-group-style.rs +++ b/src/test/compile-fail/lint-group-style.rs @@ -20,7 +20,6 @@ mod test { #[forbid(bad_style)] //~^ NOTE lint level defined here - //~^^ NOTE lint level defined here mod bad { fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name @@ -30,7 +29,6 @@ mod test { mod warn { #![warn(bad_style)] //~^ NOTE lint level defined here - //~| NOTE lint level defined here fn CamelCase() {} //~ WARN function `CamelCase` should have a snake case name diff --git a/src/test/compile-fail/lint-unconditional-recursion.rs b/src/test/compile-fail/lint-unconditional-recursion.rs index 94e189aa47f6f..bee5a2c45be6d 100644 --- a/src/test/compile-fail/lint-unconditional-recursion.rs +++ b/src/test/compile-fail/lint-unconditional-recursion.rs @@ -10,19 +10,7 @@ #![deny(unconditional_recursion)] //~^ NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here -//~| NOTE lint level defined here + #![allow(dead_code)] fn foo() { //~ ERROR function cannot return without recurring foo(); //~ NOTE recursive call site