Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 31, 2016
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
Prev Previous commit
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.
  • Loading branch information
zackmdavis committed Oct 27, 2016
commit ef6a07221d66bff1ef8edac4f9ffc39013abf256
2 changes: 1 addition & 1 deletion src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 9 additions & 8 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)>>,
Expand Down Expand Up @@ -294,25 +294,26 @@ 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
// "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>,
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
config::ErrorOutputType::Json => {
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);
}
Expand Down
22 changes: 22 additions & 0 deletions src/test/ui/span/issue-24690.rs
Original file line number Diff line number Diff line change
@@ -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);
}
32 changes: 32 additions & 0 deletions src/test/ui/span/issue-24690.stderr
Original file line number Diff line number Diff line change
@@ -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