Auto merge of #38103 - zackmdavis:lint_errors_resulting_from_lint_groups_or_warnings_meta-lint_obscure_the_original_lint_name, r=nikomatsakis

note individual lint name in messages set via lint group attribute

![lint_errors_resulting_from_lint_groups_obscure](https://cloud.githubusercontent.com/assets/1076988/20783614/c107d5c8-b749-11e6-85de-eada7f67c986.png)

Resolves #36846.

r? @jonathandturner

-----

***Update*** 16 December (new commits):
![lint_group_makeover_party](https://cloud.githubusercontent.com/assets/1076988/21284540/ff1ae2fc-c3d2-11e6-93be-d0689f5fa7a8.png)
This commit is contained in:
bors 2017-02-05 01:22:54 +00:00
commit d7777ae682
20 changed files with 263 additions and 79 deletions

View File

@ -40,8 +40,10 @@ use std::cmp;
use std::default::Default as StdDefault;
use std::mem;
use std::fmt;
use std::ops::Deref;
use syntax::attr;
use syntax::ast;
use syntax::symbol::Symbol;
use syntax_pos::{MultiSpan, Span};
use errors::{self, Diagnostic, DiagnosticBuilder};
use hir;
@ -299,8 +301,9 @@ impl LintStore {
check_lint_name_cmdline(sess, self,
&lint_name[..], level);
let lint_flag_val = Symbol::intern(&lint_name);
match self.find_lint(&lint_name[..], sess, None) {
Ok(lint_id) => self.set_level(lint_id, (level, CommandLine)),
Ok(lint_id) => self.set_level(lint_id, (level, CommandLine(lint_flag_val))),
Err(FindLintError::Removed) => { }
Err(_) => {
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
@ -310,7 +313,7 @@ impl LintStore {
Some(v) => {
v.iter()
.map(|lint_id: &LintId|
self.set_level(*lint_id, (level, CommandLine)))
self.set_level(*lint_id, (level, CommandLine(lint_flag_val))))
.collect::<Vec<()>>();
}
None => {
@ -446,35 +449,18 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
-> DiagnosticBuilder<'a>
where S: Into<MultiSpan>
{
let (mut level, source) = lvlsrc;
let (level, source) = lvlsrc;
if level == Allow {
return sess.diagnostic().struct_dummy();
}
let name = lint.name_lower();
let mut def = None;
let msg = match source {
Default => {
format!("{}, #[{}({})] on by default", msg,
level.as_str(), name)
},
CommandLine => {
format!("{} [-{} {}]", msg,
match level {
Warn => 'W', Deny => 'D', Forbid => 'F',
Allow => bug!()
}, name.replace("_", "-"))
},
Node(src) => {
def = Some(src);
msg.to_string()
}
};
// For purposes of printing, we can treat forbid as deny.
if level == Forbid { level = Deny; }
// Except for possible note details, forbid behaves like deny.
let effective_level = if level == Forbid { Deny } else { level };
let mut err = match (level, span) {
let mut err = match (effective_level, span) {
(Warn, Some(sp)) => sess.struct_span_warn(sp, &msg[..]),
(Warn, None) => sess.struct_warn(&msg[..]),
(Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]),
@ -482,6 +468,35 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
_ => bug!("impossible level in raw_emit_lint"),
};
match source {
Default => {
err.note(&format!("#[{}({})] on by default", level.as_str(), name));
},
CommandLine(lint_flag_val) => {
let flag = match level {
Warn => "-W", Deny => "-D", Forbid => "-F",
Allow => bug!("earlier conditional return should handle Allow case")
};
let hyphen_case_lint_name = name.replace("_", "-");
if lint_flag_val.as_str().deref() == name {
err.note(&format!("requested on the command line with `{} {}`",
flag, hyphen_case_lint_name));
} else {
let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
err.note(&format!("`{} {}` implied by `{} {}`",
flag, hyphen_case_lint_name, flag, hyphen_case_flag_val));
}
},
Node(lint_attr_name, src) => {
def = Some(src);
if lint_attr_name.as_str().deref() != name {
let level_str = level.as_str();
err.note(&format!("#[{}({})] implied by #[{}({})]",
level_str, name, level_str, lint_attr_name));
}
}
}
// Check for future incompatibility lints and issue a stronger warning.
if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
let explanation = format!("this was previously accepted by the compiler \
@ -649,6 +664,8 @@ pub trait LintContext<'tcx>: Sized {
}
};
let lint_attr_name = result.expect("lint attribute should be well-formed").0;
for (lint_id, level, span) in v {
let (now, now_source) = self.lints().get_level_source(lint_id);
if now == Forbid && level != Forbid {
@ -660,11 +677,11 @@ pub trait LintContext<'tcx>: Sized {
diag_builder.span_label(span, &format!("overruled by previous forbid"));
match now_source {
LintSource::Default => &mut diag_builder,
LintSource::Node(forbid_source_span) => {
LintSource::Node(_, forbid_source_span) => {
diag_builder.span_label(forbid_source_span,
&format!("`forbid` level set here"))
},
LintSource::CommandLine => {
LintSource::CommandLine(_) => {
diag_builder.note("`forbid` lint level was set on command line")
}
}.emit()
@ -672,7 +689,7 @@ pub trait LintContext<'tcx>: Sized {
let src = self.lints().get_level_source(lint_id).1;
self.level_stack().push((lint_id, (now, src)));
pushed += 1;
self.mut_lints().set_level(lint_id, (level, Node(span)));
self.mut_lints().set_level(lint_id, (level, Node(lint_attr_name, span)));
}
}
}

View File

@ -38,6 +38,7 @@ use std::ascii::AsciiExt;
use syntax_pos::Span;
use syntax::visit as ast_visit;
use syntax::ast;
use syntax::symbol::Symbol;
pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
@ -338,10 +339,10 @@ pub enum LintSource {
Default,
/// Lint level was set by an attribute.
Node(Span),
Node(ast::Name, Span),
/// Lint level was set by a command-line flag.
CommandLine,
CommandLine(Symbol),
}
pub type LevelSource = (Level, LintSource);

View File

@ -23,6 +23,7 @@ mod bar {
//~^ WARN `Foo` is ambiguous
//~| WARN hard error in a future release
//~| NOTE see issue #38260
//~| NOTE #[warn(legacy_imports)] on by default
}
}

View File

@ -9,5 +9,7 @@
// except according to those terms.
#![deny(warnings)] //~ NOTE: lint level defined here
use std::thread; //~ ERROR: unused import
use std::thread;
//~^ ERROR: unused import
//~| NOTE: #[deny(unused_imports)] implied by #[deny(warnings)]
fn main() {}

View File

@ -1,41 +0,0 @@
// Copyright 2014 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.
#![deny(bad_style)]
//~^ NOTE lint level defined here
#![allow(dead_code)]
fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
#[allow(bad_style)]
mod test {
fn CamelCase() {}
#[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
static bad: isize = 1; //~ ERROR static variable `bad` should have an upper case name
}
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
struct snake_case; //~ WARN type `snake_case` should have a camel case name
}
}
fn main() {}

View File

@ -11,15 +11,20 @@
// compile-flags: -F unused_features
// aux-build:lint_output_format.rs
#![feature(foo)] //~ ERROR unused or unknown feature
#![feature(foo)]
//~^ ERROR unused or unknown feature
//~| NOTE requested on the command line with `-F unused-features`
#![feature(test_feature)]
extern crate lint_output_format;
use lint_output_format::{foo, bar};
//~^ WARNING use of deprecated item: text,
//~^ WARNING use of deprecated item: text
//~| NOTE #[warn(deprecated)] on by default
fn main() {
let _x = foo(); //~ WARNING #[warn(deprecated)] on by default
let _x = foo();
//~^ WARNING use of deprecated item: text
//~| NOTE #[warn(deprecated)] on by default
let _y = bar();
}

View File

@ -10,11 +10,11 @@
// Parser test for #37765
fn with_parens<T: ToString>(arg: T) -> String { //~WARN dead_code
return (<T as ToString>::to_string(&arg)); //~WARN unused_parens
fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
}
fn no_parens<T: ToString>(arg: T) -> String { //~WARN dead_code
fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
return <T as ToString>::to_string(&arg);
}

View File

@ -1,4 +1,4 @@
error[E0276]: impl has stricter requirements than trait, #[deny(extra_requirement_in_impl)] on by default
error[E0276]: impl has stricter requirements than trait
--> $DIR/proj-outlives-region.rs:22:5
|
17 | fn foo() where T: 'a;
@ -7,6 +7,7 @@ error[E0276]: impl has stricter requirements than trait, #[deny(extra_requiremen
22 | fn foo() where U: 'a { } //~ ERROR E0276
| ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a`
|
= note: #[deny(extra_requirement_in_impl)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>

View File

@ -1,4 +1,4 @@
error[E0276]: impl has stricter requirements than trait, #[deny(extra_requirement_in_impl)] on by default
error[E0276]: impl has stricter requirements than trait
--> $DIR/region-unrelated.rs:22:5
|
17 | fn foo() where T: 'a;
@ -7,6 +7,7 @@ error[E0276]: impl has stricter requirements than trait, #[deny(extra_requiremen
22 | fn foo() where V: 'a { }
| ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `V: 'a`
|
= note: #[deny(extra_requirement_in_impl)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>

View File

@ -0,0 +1,15 @@
// Copyright 2017 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.
// compile-flags: -A bad-style
fn main() {
let _InappropriateCamelCasing = true;
}

View File

@ -0,0 +1,15 @@
// Copyright 2017 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.
// compile-flags: -D bad-style
fn main() {
let _InappropriateCamelCasing = true;
}

View File

@ -0,0 +1,10 @@
error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
--> $DIR/command-line-lint-group-deny.rs:14:9
|
14 | let _InappropriateCamelCasing = true;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D non-snake-case` implied by `-D bad-style`
error: aborting due to previous error

View File

@ -0,0 +1,15 @@
// Copyright 2017 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.
// compile-flags: -F bad-style
fn main() {
let _InappropriateCamelCasing = true;
}

View File

@ -0,0 +1,10 @@
error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
--> $DIR/command-line-lint-group-forbid.rs:14:9
|
14 | let _InappropriateCamelCasing = true;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-F non-snake-case` implied by `-F bad-style`
error: aborting due to previous error

View File

@ -0,0 +1,15 @@
// Copyright 2017 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.
// compile-flags: -W bad-style
fn main() {
let _InappropriateCamelCasing = true;
}

View File

@ -0,0 +1,8 @@
warning: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
--> $DIR/command-line-lint-group-warn.rs:14:9
|
14 | let _InappropriateCamelCasing = true;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-W non-snake-case` implied by `-W bad-style`

View File

@ -0,0 +1,36 @@
// Copyright 20142017 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.
#![deny(bad_style)]
#![allow(dead_code)]
fn CamelCase() {}
#[allow(bad_style)]
mod test {
fn CamelCase() {}
#[forbid(bad_style)]
mod bad {
fn CamelCase() {}
static bad: isize = 1;
}
mod warn {
#![warn(bad_style)]
fn CamelCase() {}
struct snake_case;
}
}
fn main() {}

View File

@ -0,0 +1,67 @@
error: function `CamelCase` should have a snake case name such as `camel_case`
--> $DIR/lint-group-style.rs:14:1
|
14 | fn CamelCase() {}
| ^^^^^^^^^^^^^^^^^
|
= note: #[deny(non_snake_case)] implied by #[deny(bad_style)]
note: lint level defined here
--> $DIR/lint-group-style.rs:11:9
|
11 | #![deny(bad_style)]
| ^^^^^^^^^
error: function `CamelCase` should have a snake case name such as `camel_case`
--> $DIR/lint-group-style.rs:22:9
|
22 | fn CamelCase() {}
| ^^^^^^^^^^^^^^^^^
|
= note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)]
note: lint level defined here
--> $DIR/lint-group-style.rs:20:14
|
20 | #[forbid(bad_style)]
| ^^^^^^^^^
error: static variable `bad` should have an upper case name such as `BAD`
--> $DIR/lint-group-style.rs:24:9
|
24 | static bad: isize = 1;
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)]
note: lint level defined here
--> $DIR/lint-group-style.rs:20:14
|
20 | #[forbid(bad_style)]
| ^^^^^^^^^
warning: function `CamelCase` should have a snake case name such as `camel_case`
--> $DIR/lint-group-style.rs:30:9
|
30 | fn CamelCase() {}
| ^^^^^^^^^^^^^^^^^
|
= note: #[warn(non_snake_case)] implied by #[warn(bad_style)]
note: lint level defined here
--> $DIR/lint-group-style.rs:28:17
|
28 | #![warn(bad_style)]
| ^^^^^^^^^
warning: type `snake_case` should have a camel case name such as `SnakeCase`
--> $DIR/lint-group-style.rs:32:9
|
32 | struct snake_case;
| ^^^^^^^^^^^^^^^^^^
|
= note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)]
note: lint level defined here
--> $DIR/lint-group-style.rs:28:17
|
28 | #![warn(bad_style)]
| ^^^^^^^^^
error: aborting due to 3 previous errors

View File

@ -4,6 +4,7 @@ error: variable `theTwo` should have a snake case name such as `the_two`
19 | let theTwo = 2;
| ^^^^^^
|
= note: #[deny(non_snake_case)] implied by #[deny(warnings)]
note: lint level defined here
--> $DIR/issue-24690.rs:16:9
|
@ -15,6 +16,8 @@ error: variable `theOtherTwo` should have a snake case name such as `the_other_t
|
20 | let theOtherTwo = 2;
| ^^^^^^^^^^^
|
= note: #[deny(non_snake_case)] implied by #[deny(warnings)]
error: unused variable: `theOtherTwo`
--> $DIR/issue-24690.rs:20:9
@ -22,6 +25,7 @@ error: unused variable: `theOtherTwo`
20 | let theOtherTwo = 2;
| ^^^^^^^^^^^
|
= note: #[deny(unused_variables)] implied by #[deny(warnings)]
note: lint level defined here
--> $DIR/issue-24690.rs:16:9
|

View File

@ -1,6 +1,8 @@
warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`, #[warn(unused_imports)] on by default
warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`
--> $DIR/multispan-import-lint.rs:11:16
|
11 | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
| ^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default