introing one-time diagnostics: only emit "lint level defined here" once

We introduce a new `one_time_diagnostics` field on
`rustc::session::Session` to hold a hashset of diagnostic messages we've
set once but don't want to see again (as uniquified by span and message
text), "lint level defined here" being the motivating example dealt with
here.

This is in the matter of #24690.
This commit is contained in:
Zack M. Davis 2016-10-15 10:28:12 -07:00
parent 8e05e7ee3c
commit 1bfa1d51fd
4 changed files with 28 additions and 18 deletions

View File

@ -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

View File

@ -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<lint::LintStore>,
pub lints: RefCell<NodeMap<Vec<(lint::LintId, Span, String)>>>,
/// 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<FnvHashSet<(Span, String)>>,
pub plugin_llvm_passes: RefCell<Vec<String>>,
pub mir_passes: RefCell<mir_pass::Passes>,
pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
@ -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()),

View File

@ -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

View File

@ -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