Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. So the key is the span+message, but it's possible that the level for many lints is set at one point (e.g., #[allow(warnings)]). Do we want to issue one note per kind of lint, or just one per span? I'm actually not sure =)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaning towards one-per-lint (ef6a072).

}

err
Expand Down
27 changes: 26 additions & 1 deletion src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)>>,
Expand Down Expand Up @@ -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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: you can write

let fresh = self.one_time_diagnostics.borrow_mut().insert(&span_message);
if fresh {
    diag_builder.span_note(span, &message);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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()
}
Expand Down Expand Up @@ -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()),
Expand Down
2 changes: 0 additions & 2 deletions src/test/compile-fail/lint-group-style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

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

Expand Down
14 changes: 1 addition & 13 deletions src/test/compile-fail/lint-unconditional-recursion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down