deduplicate one-time diagnostics on lint ID as well as span and message

Some lint-level attributes (like `bad-style`, or, more dramatically,
`warnings`) can affect more than one lint; it seems fairer to point out
the attribute once for each distinct lint affected. Also, a UI test is
added. This remains in the matter of #24690.
This commit is contained in:
Zack M. Davis 2016-10-26 23:07:38 -07:00
parent 8d1da8452c
commit ef6a07221d
4 changed files with 64 additions and 9 deletions

View file

@ -452,7 +452,7 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
}
if let Some(span) = def {
sess.diag_span_note_once(&mut err, span, "lint level defined here");
sess.diag_span_note_once(&mut err, lint, span, "lint level defined here");
}
err

View file

@ -75,10 +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
/// 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<(Span, String)>>,
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)>>,
@ -294,8 +294,8 @@ impl Session {
}
/// Analogous to calling `.span_note` on the given DiagnosticBuilder, but
/// deduplicates on span and message for this `Session` if we're not
/// outputting in JSON mode.
/// 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
@ -303,7 +303,7 @@ impl Session {
// 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) {
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
@ -311,8 +311,9 @@ impl Session {
diag_builder.span_note(span, &message);
},
_ => {
let span_message = (span, message.to_owned());
let fresh = self.one_time_diagnostics.borrow_mut().insert(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);
}

View file

@ -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);
}

View file

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