diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 362117d860a5c..32bc81e947037 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -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::>(); } None => { @@ -446,35 +449,18 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, -> DiagnosticBuilder<'a> where S: Into { - 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))); } } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index d12065ca86e14..e9f603db15d62 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -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); diff --git a/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs b/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs index eb36129799a4e..1d67bf3a1cdda 100644 --- a/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs +++ b/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs @@ -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 } } diff --git a/src/test/compile-fail/issue-30730.rs b/src/test/compile-fail/issue-30730.rs index 82804bb747406..086938334c78a 100644 --- a/src/test/compile-fail/issue-30730.rs +++ b/src/test/compile-fail/issue-30730.rs @@ -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() {} diff --git a/src/test/compile-fail/lint-group-style.rs b/src/test/compile-fail/lint-group-style.rs deleted file mode 100644 index b2e6072c9855c..0000000000000 --- a/src/test/compile-fail/lint-group-style.rs +++ /dev/null @@ -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 or the MIT license -// , 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() {} diff --git a/src/test/compile-fail/lint-output-format-2.rs b/src/test/compile-fail/lint-output-format-2.rs index 2f74325d19c7d..0e68ff752e5a9 100644 --- a/src/test/compile-fail/lint-output-format-2.rs +++ b/src/test/compile-fail/lint-output-format-2.rs @@ -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(); } diff --git a/src/test/run-pass/path-lookahead.rs b/src/test/run-pass/path-lookahead.rs index 017259af190fc..5c195c8a4c63a 100644 --- a/src/test/run-pass/path-lookahead.rs +++ b/src/test/run-pass/path-lookahead.rs @@ -10,11 +10,11 @@ // Parser test for #37765 -fn with_parens(arg: T) -> String { //~WARN dead_code - return (::to_string(&arg)); //~WARN unused_parens +fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` + return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value } -fn no_parens(arg: T) -> String { //~WARN dead_code +fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` return ::to_string(&arg); } diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr index 021b571fe793c..2a707c6eb8b10 100644 --- a/src/test/ui/compare-method/proj-outlives-region.stderr +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -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 diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr index 4df337c525743..9e822bd8b0790 100644 --- a/src/test/ui/compare-method/region-unrelated.stderr +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -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 diff --git a/src/test/ui/lint/command-line-lint-group-allow.rs b/src/test/ui/lint/command-line-lint-group-allow.rs new file mode 100644 index 0000000000000..cdb9684933d9b --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-allow.rs @@ -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 or the MIT license +// , 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; +} diff --git a/src/test/ui/lint/command-line-lint-group-deny.rs b/src/test/ui/lint/command-line-lint-group-deny.rs new file mode 100644 index 0000000000000..1248601c1e44a --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-deny.rs @@ -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 or the MIT license +// , 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; +} diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr new file mode 100644 index 0000000000000..23fac66cc6c98 --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-deny.stderr @@ -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 + diff --git a/src/test/ui/lint/command-line-lint-group-forbid.rs b/src/test/ui/lint/command-line-lint-group-forbid.rs new file mode 100644 index 0000000000000..ae16db44864c9 --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-forbid.rs @@ -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 or the MIT license +// , 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; +} diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr new file mode 100644 index 0000000000000..0babd7f6fe47a --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr @@ -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 + diff --git a/src/test/ui/lint/command-line-lint-group-warn.rs b/src/test/ui/lint/command-line-lint-group-warn.rs new file mode 100644 index 0000000000000..7d65c802788bf --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-warn.rs @@ -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 or the MIT license +// , 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; +} diff --git a/src/test/ui/lint/command-line-lint-group-warn.stderr b/src/test/ui/lint/command-line-lint-group-warn.stderr new file mode 100644 index 0000000000000..998c892c7e349 --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-warn.stderr @@ -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` + diff --git a/src/test/ui/lint/lint-group-style.rs b/src/test/ui/lint/lint-group-style.rs new file mode 100644 index 0000000000000..2bd760e417a89 --- /dev/null +++ b/src/test/ui/lint/lint-group-style.rs @@ -0,0 +1,36 @@ +// Copyright 2014–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 or the MIT license +// , 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() {} diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr new file mode 100644 index 0000000000000..9c0f4866af690 --- /dev/null +++ b/src/test/ui/lint/lint-group-style.stderr @@ -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 + diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index dbe5e31287e97..c4f2616f5945b 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -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 | diff --git a/src/test/ui/span/multispan-import-lint.stderr b/src/test/ui/span/multispan-import-lint.stderr index b581584eee7e2..4b1ca7f98bbf6 100644 --- a/src/test/ui/span/multispan-import-lint.stderr +++ b/src/test/ui/span/multispan-import-lint.stderr @@ -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