]> git.lizzy.rs Git - rust.git/commitdiff
note individual lint name set via lint group attribute in notes
authorZack M. Davis <code@zackmdavis.net>
Fri, 6 Jan 2017 02:55:36 +0000 (18:55 -0800)
committerZack M. Davis <code@zackmdavis.net>
Sat, 4 Feb 2017 18:44:22 +0000 (10:44 -0800)
Warning or error messages set via a lint group attribute
(e.g. `#[deny(warnings)]`) should still make it clear which individual
lint (by name) was triggered, similarly to how we include "on by
default" language for default lints. This—and, while we're here, the
existing "on by default" language—can be tucked into a note rather than
cluttering the main error message. This occasions the slightest of
refactorings (we now have to get the diagnostic-builder with the main
message first, before matching on the lint source).

This is in the matter of #36846.

src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/test/compile-fail/imports/rfc-1560-warning-cycle.rs
src/test/compile-fail/issue-30730.rs
src/test/compile-fail/lint-group-style.rs
src/test/compile-fail/lint-output-format-2.rs
src/test/run-pass/path-lookahead.rs
src/test/ui/compare-method/proj-outlives-region.stderr
src/test/ui/compare-method/region-unrelated.stderr
src/test/ui/span/issue-24690.stderr
src/test/ui/span/multispan-import-lint.stderr

index 362117d860a5c15f3aece6d8d2c1a9f497a4f634..62f19412d52f0da7c8c2e491b9a904d5685fac67 100644 (file)
@@ -40,6 +40,7 @@
 use std::default::Default as StdDefault;
 use std::mem;
 use std::fmt;
+use std::ops::Deref;
 use syntax::attr;
 use syntax::ast;
 use syntax_pos::{MultiSpan, Span};
@@ -446,35 +447,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 +466,27 @@ 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 => {
+            err.note(&format!("[-{} {}]",
+                              match level {
+                                  Warn => 'W', Deny => 'D', Forbid => 'F',
+                                  Allow => bug!()
+                              }, name.replace("_", "-")));
+        },
+        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!("#[{}({})] implies #[{}({})]",
+                                  level_str, lint_attr_name, level_str, 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 +654,8 @@ fn with_lint_attrs<F>(&mut self,
                 }
             };
 
+            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,7 +667,7 @@ fn with_lint_attrs<F>(&mut self,
                     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"))
                         },
@@ -672,7 +679,7 @@ fn with_lint_attrs<F>(&mut self,
                     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)));
                 }
             }
         }
index d12065ca86e144c5d0e682e33b596ed4122d5275..9c2a892a5fc7d92984317b40a6cd1880cea4b2b7 100644 (file)
@@ -338,7 +338,7 @@ 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,
index eb36129799a4e21e833b7927f1af65df1f956c13..1d67bf3a1cddad7617c3cbf9cc73fa0ca399020a 100644 (file)
@@ -23,6 +23,7 @@ fn f(_: Foo) {}
         //~^ WARN `Foo` is ambiguous
         //~| WARN hard error in a future release
         //~| NOTE see issue #38260
+        //~| NOTE #[warn(legacy_imports)] on by default
     }
 }
 
index 82804bb747406652640df86fffcd594a607476fa..6082740f427d711224742b25ece8b6a9021ea1ca 100644 (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(warnings)] implies #[deny(unused_imports)]
 fn main() {}
index b2e6072c9855c38f93db02865e105befb2be182f..a8c377034756a43800f0aefa5df8f9cffccda9d3 100644 (file)
@@ -12,7 +12,9 @@
 //~^ NOTE lint level defined here
 #![allow(dead_code)]
 
-fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
+fn CamelCase() {}
+//~^ ERROR function `CamelCase` should have a snake case name
+//~| NOTE #[deny(bad_style)] implies #[deny(non_snake_case)]
 
 #[allow(bad_style)]
 mod test {
@@ -22,9 +24,13 @@ fn CamelCase() {}
     //~^ NOTE lint level defined here
     //~^^ NOTE lint level defined here
     mod bad {
-        fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name
+        fn CamelCase() {}
+        //~^ ERROR function `CamelCase` should have a snake case name
+        //~| NOTE #[forbid(bad_style)] implies #[forbid(non_snake_case)]
 
-        static bad: isize = 1; //~ ERROR static variable `bad` should have an upper case name
+        static bad: isize = 1;
+        //~^ ERROR static variable `bad` should have an upper case name
+        //~| NOTE #[forbid(bad_style)] implies #[forbid(non_upper_case_globals)]
     }
 
     mod warn {
@@ -32,9 +38,13 @@ mod warn {
         //~^ NOTE lint level defined here
         //~| NOTE lint level defined here
 
-        fn CamelCase() {} //~ WARN function `CamelCase` should have a snake case name
+        fn CamelCase() {}
+        //~^ WARN function `CamelCase` should have a snake case name
+        //~| NOTE #[warn(bad_style)] implies #[warn(non_snake_case)]
 
-        struct snake_case; //~ WARN type `snake_case` should have a camel case name
+        struct snake_case;
+        //~^ WARN type `snake_case` should have a camel case name
+        //~| NOTE #[warn(bad_style)] implies #[warn(non_camel_case_types)]
     }
 }
 
index 2f74325d19c7d587389ac654de1a3db14dece71b..8b76bedb003c008764099886147975590316d64d 100644 (file)
 // 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 [-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();
 }
index 017259af190fc2d861f0d0375def08b362a0cbcb..5c195c8a4c63a37ddd09a1a4d21fa31967709b44 100644 (file)
 
 // 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);
 }
 
index 021b571fe793cd77c84ca3f1a302db1655883077..2a707c6eb8b103b428de32c4fb5f2c64f848b38a 100644 (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>
 
index 4df337c525743f778e21582776fe22c1f9c2194e..9e822bd8b0790097ff4832bd78edadf41677b8e9 100644 (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>
 
index dbe5e31287e9793b2d3be74d91b18b9aa391ef46..623bb4a0d26973664c268e2ff499a20362fc8bb0 100644 (file)
@@ -4,6 +4,7 @@ error: variable `theTwo` should have a snake case name such as `the_two`
 19 |     let theTwo = 2;
    |         ^^^^^^
    |
+   = note: #[deny(warnings)] implies #[deny(non_snake_case)]
 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(warnings)] implies #[deny(non_snake_case)]
 
 error: unused variable: `theOtherTwo`
   --> $DIR/issue-24690.rs:20:9
@@ -22,6 +25,7 @@ error: unused variable: `theOtherTwo`
 20 |     let theOtherTwo = 2;
    |         ^^^^^^^^^^^
    |
+   = note: #[deny(warnings)] implies #[deny(unused_variables)]
 note: lint level defined here
   --> $DIR/issue-24690.rs:16:9
    |
index b581584eee7e2471cff58053d25716a01f208010..4b1ca7f98bbf65d1d2ad8bd2e73462f5dcd16087 100644 (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