about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-10-02 07:03:26 +0000
committerbors <bors@rust-lang.org>2017-10-02 07:03:26 +0000
commit9ae6ed78acf9dc865e2300a7db556389eed9692d (patch)
treea88473a1d7bb97b8a08866c02e68f965cad25362 /src
parent2146c613d12de8dc44bc26e50af55251fc7e4f9c (diff)
parent8a14022c5d31e1648bd1212a52a9f1a9ddbf3fa1 (diff)
downloadrust-9ae6ed78acf9dc865e2300a7db556389eed9692d.tar.gz
rust-9ae6ed78acf9dc865e2300a7db556389eed9692d.zip
Auto merge of #44942 - zackmdavis:lint_suggestions, r=estebank
code suggestions for unused-mut, while-true, deprecated-attribute, and unused-parens lints

![lint_suggestions](https://user-images.githubusercontent.com/1076988/31044068-b2074de8-a57c-11e7-9319-6668508b6d1f.png)

r? @estebank
Diffstat (limited to 'src')
-rw-r--r--src/librustc_errors/diagnostic.rs4
-rw-r--r--src/librustc_errors/emitter.rs2
-rw-r--r--src/librustc_lint/builtin.rs19
-rw-r--r--src/librustc_lint/unused.rs48
-rw-r--r--src/libsyntax/feature_gate.rs3
-rw-r--r--src/test/compile-fail/feature-gate-no-debug.rs2
-rw-r--r--src/test/compile-fail/issue-1962.rs2
-rw-r--r--src/test/ui/lint/suggestions.rs20
-rw-r--r--src/test/ui/lint/suggestions.stderr45
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.rs25
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.stderr1
-rw-r--r--src/test/ui/path-lookahead.stderr2
12 files changed, 153 insertions, 20 deletions
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 9aae188f9ec..02c0307e98c 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -208,7 +208,7 @@ impl Diagnostic {
     /// Prints out a message with a suggested edit of the code. If the suggestion is presented
     /// inline it will only show the text message and not the text.
     ///
-    /// See `diagnostic::CodeSuggestion` for more information.
+    /// See `CodeSuggestion` for more information.
     pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitution_parts: vec![Substitution {
@@ -235,7 +235,7 @@ impl Diagnostic {
     /// * may look like "to do xyz, use" or "to do xyz, use abc"
     /// * may contain a name of a function, variable or type, but not whole expressions
     ///
-    /// See `diagnostic::CodeSuggestion` for more information.
+    /// See `CodeSuggestion` for more information.
     pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitution_parts: vec![Substitution {
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index daa132dbf62..2f994de396c 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -48,7 +48,7 @@ impl Emitter for EmitterWriter {
                sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
                 let substitution = &sugg.substitution_parts[0].substitutions[0];
                 let msg = if substitution.len() == 0 || !sugg.show_code_when_inline {
-                    // This substitution is only removal or we explicitely don't want to show the
+                    // This substitution is only removal or we explicitly don't want to show the
                     // code inline, don't show it
                     format!("help: {}", sugg.msg)
                 } else {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index f3bf37c11a5..7f331418d42 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -76,9 +76,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WhileTrue {
             if let hir::ExprLit(ref lit) = cond.node {
                 if let ast::LitKind::Bool(true) = lit.node {
                     if lit.span.ctxt() == SyntaxContext::empty() {
-                        cx.span_lint(WHILE_TRUE,
-                                    e.span,
-                                    "denote infinite loops with loop { ... }");
+                        let msg = "denote infinite loops with `loop { ... }`";
+                        let mut err = cx.struct_span_lint(WHILE_TRUE, e.span, msg);
+                        let condition_span = cx.tcx.sess.codemap().def_span(e.span);
+                        err.span_suggestion_short(condition_span,
+                                                  "use `loop`",
+                                                  "loop".to_owned());
+                        err.emit();
                     }
                 }
             }
@@ -650,10 +654,11 @@ impl EarlyLintPass for DeprecatedAttr {
                                              ref name,
                                              ref reason,
                                              _) = g {
-                    cx.span_lint(DEPRECATED,
-                                 attr.span,
-                                 &format!("use of deprecated attribute `{}`: {}. See {}",
-                                          name, reason, link));
+                    let msg = format!("use of deprecated attribute `{}`: {}. See {}",
+                                      name, reason, link);
+                    let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg);
+                    err.span_suggestion_short(attr.span, "remove this attribute", "".to_owned());
+                    err.emit();
                 }
                 return;
             }
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index b97920dd18b..e2ade19b6e2 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -22,6 +22,7 @@ use syntax::attr;
 use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType};
 use syntax::symbol::keywords;
 use syntax::ptr::P;
+use syntax::print::pprust;
 use syntax::util::parser;
 use syntax_pos::Span;
 
@@ -70,9 +71,13 @@ impl UnusedMut {
         let used_mutables = cx.tcx.used_mut_nodes.borrow();
         for (_, v) in &mutables {
             if !v.iter().any(|e| used_mutables.contains(e)) {
-                cx.span_lint(UNUSED_MUT,
-                             cx.tcx.hir.span(v[0]),
-                             "variable does not need to be mutable");
+                let binding_span = cx.tcx.hir.span(v[0]);
+                let mut_span = cx.tcx.sess.codemap().span_until_char(binding_span, ' ');
+                let mut err = cx.struct_span_lint(UNUSED_MUT,
+                                                  binding_span,
+                                                  "variable does not need to be mutable");
+                err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned());
+                err.emit();
             }
         }
     }
@@ -325,9 +330,40 @@ impl UnusedParens {
             let necessary = struct_lit_needs_parens &&
                             parser::contains_exterior_struct_lit(&inner);
             if !necessary {
-                cx.span_lint(UNUSED_PARENS,
-                             value.span,
-                             &format!("unnecessary parentheses around {}", msg))
+                let span_msg = format!("unnecessary parentheses around {}", msg);
+                let mut err = cx.struct_span_lint(UNUSED_PARENS,
+                                                  value.span,
+                                                  &span_msg);
+                // Remove exactly one pair of parentheses (rather than naïvely
+                // stripping all paren characters)
+                let mut ate_left_paren = false;
+                let mut ate_right_paren = false;
+                let parens_removed = pprust::expr_to_string(value)
+                    .trim_matches(|c| {
+                        match c {
+                            '(' => {
+                                if ate_left_paren {
+                                    false
+                                } else {
+                                    ate_left_paren = true;
+                                    true
+                                }
+                            },
+                            ')' => {
+                                if ate_right_paren {
+                                    false
+                                } else {
+                                    ate_right_paren = true;
+                                    true
+                                }
+                            },
+                            _ => false,
+                        }
+                    }).to_owned();
+                err.span_suggestion_short(value.span,
+                                          "remove these parentheses",
+                                          parens_removed);
+                err.emit();
             }
         }
     }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index e92a7484f33..f6e85ed6725 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -824,7 +824,8 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
     ("no_debug", Whitelisted, Gated(
         Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
         "no_debug",
-        "the `#[no_debug]` attribute is an experimental feature",
+        "the `#[no_debug]` attribute was an experimental feature that has been \
+         deprecated due to lack of demand",
         cfg_fn!(no_debug))),
     ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
                                                        "omit_gdb_pretty_printer_section",
diff --git a/src/test/compile-fail/feature-gate-no-debug.rs b/src/test/compile-fail/feature-gate-no-debug.rs
index 9815db6550d..d21493de50a 100644
--- a/src/test/compile-fail/feature-gate-no-debug.rs
+++ b/src/test/compile-fail/feature-gate-no-debug.rs
@@ -10,5 +10,5 @@
 
 #![allow(deprecated)]
 
-#[no_debug] //~ ERROR the `#[no_debug]` attribute is
+#[no_debug] //~ ERROR the `#[no_debug]` attribute was
 fn main() {}
diff --git a/src/test/compile-fail/issue-1962.rs b/src/test/compile-fail/issue-1962.rs
index db3e9c23b76..9de3040bb61 100644
--- a/src/test/compile-fail/issue-1962.rs
+++ b/src/test/compile-fail/issue-1962.rs
@@ -11,7 +11,7 @@
 // compile-flags: -D while-true
 fn main() {
   let mut i = 0;
-  while true  { //~ ERROR denote infinite loops with loop
+  while true  { //~ ERROR denote infinite loops with `loop
     i += 1;
     if i == 5 { break; }
   }
diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs
new file mode 100644
index 00000000000..874124a7d36
--- /dev/null
+++ b/src/test/ui/lint/suggestions.rs
@@ -0,0 +1,20 @@
+// 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.
+
+#![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
+#![feature(no_debug)]
+
+#[no_debug] // should suggest removal of deprecated attribute
+fn main() {
+    while true { // should suggest `loop`
+        let mut a = (1); // should suggest no `mut`, no parens
+        println!("{}", a);
+    }
+}
diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr
new file mode 100644
index 00000000000..5b2a4f589f7
--- /dev/null
+++ b/src/test/ui/lint/suggestions.stderr
@@ -0,0 +1,45 @@
+warning: unnecessary parentheses around assigned value
+  --> $DIR/suggestions.rs:17:21
+   |
+17 |         let mut a = (1); // should suggest no `mut`, no parens
+   |                     ^^^ help: remove these parentheses
+   |
+   = note: #[warn(unused_parens)] on by default
+
+warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
+  --> $DIR/suggestions.rs:14:1
+   |
+14 | #[no_debug] // should suggest removal of deprecated attribute
+   | ^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: #[warn(deprecated)] on by default
+
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/suggestions.rs:16:5
+   |
+16 |       while true { // should suggest `loop`
+   |       ^---------
+   |       |
+   |  _____help: use `loop`
+   | |
+17 | |         let mut a = (1); // should suggest no `mut`, no parens
+18 | |         println!("{}", a);
+19 | |     }
+   | |_____^
+   |
+   = note: #[warn(while_true)] on by default
+
+warning: variable does not need to be mutable
+  --> $DIR/suggestions.rs:17:13
+   |
+17 |         let mut a = (1); // should suggest no `mut`, no parens
+   |             ---^^
+   |             |
+   |             help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/suggestions.rs:11:9
+   |
+11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
+   |         ^^^^^^^^^^
+
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs
new file mode 100644
index 00000000000..d7cbd11472a
--- /dev/null
+++ b/src/test/ui/lint/unused_parens_json_suggestion.rs
@@ -0,0 +1,25 @@
+// 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: --error-format json
+
+// ignore-windows (see Issue #44968)
+
+// The output for humans should just highlight the whole span without showing
+// the suggested replacement, but we also want to test that suggested
+// replacement only removes one set of parentheses, rather than naïvely
+// stripping away any starting or ending parenthesis characters—hence this
+// test of the JSON error format.
+
+fn main() {
+    // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not
+    // the malformed `1 / (2 + 3`
+    let _a = (1 / (2 + 3));
+}
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr
new file mode 100644
index 00000000000..140224e0814
--- /dev/null
+++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr
@@ -0,0 +1 @@
+{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1014,"byte_end":1027,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"#[warn(unused_parens)] on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1014,"byte_end":1027,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":"    let _a = 1 / (2 + 3);"}],"rendered":null}
diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr
index 1d4ab35046b..19e22b3f6f9 100644
--- a/src/test/ui/path-lookahead.stderr
+++ b/src/test/ui/path-lookahead.stderr
@@ -2,7 +2,7 @@ warning: unnecessary parentheses around `return` value
   --> $DIR/path-lookahead.rs:18:10
    |
 18 |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
    |
    = note: #[warn(unused_parens)] on by default