diff options
| author | bors <bors@rust-lang.org> | 2016-10-31 10:56:25 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-10-31 10:56:25 -0700 |
| commit | f26eedb571c8e3f55385f3933be256689deed277 (patch) | |
| tree | 3ecbcebf7c5c6fddb41bbe2b341c264bf9accd04 | |
| parent | bf5b824c1cb1fa5ec9b060f9b552cf7fd7465f01 (diff) | |
| parent | ef6a07221d66bff1ef8edac4f9ffc39013abf256 (diff) | |
| download | rust-f26eedb571c8e3f55385f3933be256689deed277.tar.gz rust-f26eedb571c8e3f55385f3933be256689deed277.zip | |
Auto merge of #37191 - zackmdavis:we_heard_you_the_first_time_really, r=nikomatsakis
introing one-time diagnostics: only emit "lint level defined here" once This is a revised resubmission of PR #34084 (which was closed due to inactivity on account of time constraints on the author's part). --- 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. --- r? @nikomatsakis
| -rw-r--r-- | src/librustc/lint/context.rs | 3 | ||||
| -rw-r--r-- | src/librustc/session/mod.rs | 36 | ||||
| -rw-r--r-- | src/test/ui/span/issue-24690.rs | 22 | ||||
| -rw-r--r-- | src/test/ui/span/issue-24690.stderr | 32 |
4 files changed, 90 insertions, 3 deletions
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 81d3d440b56..cf4115e37cd 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, lint, span, "lint level defined here"); } err diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index d002aba595b..ce3f2be54b2 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<lint::LintStore>, pub lints: RefCell<NodeMap<Vec<(lint::LintId, Span, String)>>>, + /// Set of (LintId, 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<(lint::LintId, 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,35 @@ 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 lint ID, span, and message for this `Session` if we're + /// not outputting in JSON mode. + // + // FIXME: if the need arises for one-time diagnostics other than + // `span_note`, we almost certainly want to generalize this + // "check/insert-into 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>, + lint: &'static lint::Lint, span: Span, message: &str) { + match self.opts.error_format { + // when outputting JSON for tool consumption, the tool might want + // the duplicates + config::ErrorOutputType::Json => { + diag_builder.span_note(span, &message); + }, + _ => { + let lint_id = lint::LintId::of(lint); + let id_span_message = (lint_id, span, message.to_owned()); + let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message); + if fresh { + diag_builder.span_note(span, &message); + } + } + } + } + pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { self.parse_sess.codemap() } @@ -561,6 +594,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/ui/span/issue-24690.rs b/src/test/ui/span/issue-24690.rs new file mode 100644 index 00000000000..def0d9aced3 --- /dev/null +++ b/src/test/ui/span/issue-24690.rs @@ -0,0 +1,22 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A test to ensure that helpful `note` messages aren't emitted more often +//! than necessary. + +// Although there are three errors, we should only get two "lint level defined +// here" notes pointing at the `warnings` span, one for each error type. +#![deny(warnings)] + +fn main() { + let theTwo = 2; + let theOtherTwo = 2; + println!("{}", theTwo); +} diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr new file mode 100644 index 00000000000..0d2a2ef7516 --- /dev/null +++ b/src/test/ui/span/issue-24690.stderr @@ -0,0 +1,32 @@ +error: unused variable: `theOtherTwo` + --> $DIR/issue-24690.rs:20:9 + | +20 | let theOtherTwo = 2; + | ^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-24690.rs:16:9 + | +16 | #![deny(warnings)] + | ^^^^^^^^ + +error: variable `theTwo` should have a snake case name such as `the_two` + --> $DIR/issue-24690.rs:19:9 + | +19 | let theTwo = 2; + | ^^^^^^ + | +note: lint level defined here + --> $DIR/issue-24690.rs:16:9 + | +16 | #![deny(warnings)] + | ^^^^^^^^ + +error: variable `theOtherTwo` should have a snake case name such as `the_other_two` + --> $DIR/issue-24690.rs:20:9 + | +20 | let theOtherTwo = 2; + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + |
