Skip to content

Commit 9ae6ed7

Browse files
committed
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
2 parents 2146c61 + 8a14022 commit 9ae6ed7

12 files changed

+153
-20
lines changed

src/librustc_errors/diagnostic.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl Diagnostic {
208208
/// Prints out a message with a suggested edit of the code. If the suggestion is presented
209209
/// inline it will only show the text message and not the text.
210210
///
211-
/// See `diagnostic::CodeSuggestion` for more information.
211+
/// See `CodeSuggestion` for more information.
212212
pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
213213
self.suggestions.push(CodeSuggestion {
214214
substitution_parts: vec![Substitution {
@@ -235,7 +235,7 @@ impl Diagnostic {
235235
/// * may look like "to do xyz, use" or "to do xyz, use abc"
236236
/// * may contain a name of a function, variable or type, but not whole expressions
237237
///
238-
/// See `diagnostic::CodeSuggestion` for more information.
238+
/// See `CodeSuggestion` for more information.
239239
pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
240240
self.suggestions.push(CodeSuggestion {
241241
substitution_parts: vec![Substitution {

src/librustc_errors/emitter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl Emitter for EmitterWriter {
4848
sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
4949
let substitution = &sugg.substitution_parts[0].substitutions[0];
5050
let msg = if substitution.len() == 0 || !sugg.show_code_when_inline {
51-
// This substitution is only removal or we explicitely don't want to show the
51+
// This substitution is only removal or we explicitly don't want to show the
5252
// code inline, don't show it
5353
format!("help: {}", sugg.msg)
5454
} else {

src/librustc_lint/builtin.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WhileTrue {
7676
if let hir::ExprLit(ref lit) = cond.node {
7777
if let ast::LitKind::Bool(true) = lit.node {
7878
if lit.span.ctxt() == SyntaxContext::empty() {
79-
cx.span_lint(WHILE_TRUE,
80-
e.span,
81-
"denote infinite loops with loop { ... }");
79+
let msg = "denote infinite loops with `loop { ... }`";
80+
let mut err = cx.struct_span_lint(WHILE_TRUE, e.span, msg);
81+
let condition_span = cx.tcx.sess.codemap().def_span(e.span);
82+
err.span_suggestion_short(condition_span,
83+
"use `loop`",
84+
"loop".to_owned());
85+
err.emit();
8286
}
8387
}
8488
}
@@ -650,10 +654,11 @@ impl EarlyLintPass for DeprecatedAttr {
650654
ref name,
651655
ref reason,
652656
_) = g {
653-
cx.span_lint(DEPRECATED,
654-
attr.span,
655-
&format!("use of deprecated attribute `{}`: {}. See {}",
656-
name, reason, link));
657+
let msg = format!("use of deprecated attribute `{}`: {}. See {}",
658+
name, reason, link);
659+
let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg);
660+
err.span_suggestion_short(attr.span, "remove this attribute", "".to_owned());
661+
err.emit();
657662
}
658663
return;
659664
}

src/librustc_lint/unused.rs

+42-6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use syntax::attr;
2222
use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType};
2323
use syntax::symbol::keywords;
2424
use syntax::ptr::P;
25+
use syntax::print::pprust;
2526
use syntax::util::parser;
2627
use syntax_pos::Span;
2728

@@ -70,9 +71,13 @@ impl UnusedMut {
7071
let used_mutables = cx.tcx.used_mut_nodes.borrow();
7172
for (_, v) in &mutables {
7273
if !v.iter().any(|e| used_mutables.contains(e)) {
73-
cx.span_lint(UNUSED_MUT,
74-
cx.tcx.hir.span(v[0]),
75-
"variable does not need to be mutable");
74+
let binding_span = cx.tcx.hir.span(v[0]);
75+
let mut_span = cx.tcx.sess.codemap().span_until_char(binding_span, ' ');
76+
let mut err = cx.struct_span_lint(UNUSED_MUT,
77+
binding_span,
78+
"variable does not need to be mutable");
79+
err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned());
80+
err.emit();
7681
}
7782
}
7883
}
@@ -325,9 +330,40 @@ impl UnusedParens {
325330
let necessary = struct_lit_needs_parens &&
326331
parser::contains_exterior_struct_lit(&inner);
327332
if !necessary {
328-
cx.span_lint(UNUSED_PARENS,
329-
value.span,
330-
&format!("unnecessary parentheses around {}", msg))
333+
let span_msg = format!("unnecessary parentheses around {}", msg);
334+
let mut err = cx.struct_span_lint(UNUSED_PARENS,
335+
value.span,
336+
&span_msg);
337+
// Remove exactly one pair of parentheses (rather than naïvely
338+
// stripping all paren characters)
339+
let mut ate_left_paren = false;
340+
let mut ate_right_paren = false;
341+
let parens_removed = pprust::expr_to_string(value)
342+
.trim_matches(|c| {
343+
match c {
344+
'(' => {
345+
if ate_left_paren {
346+
false
347+
} else {
348+
ate_left_paren = true;
349+
true
350+
}
351+
},
352+
')' => {
353+
if ate_right_paren {
354+
false
355+
} else {
356+
ate_right_paren = true;
357+
true
358+
}
359+
},
360+
_ => false,
361+
}
362+
}).to_owned();
363+
err.span_suggestion_short(value.span,
364+
"remove these parentheses",
365+
parens_removed);
366+
err.emit();
331367
}
332368
}
333369
}

src/libsyntax/feature_gate.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,8 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
824824
("no_debug", Whitelisted, Gated(
825825
Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
826826
"no_debug",
827-
"the `#[no_debug]` attribute is an experimental feature",
827+
"the `#[no_debug]` attribute was an experimental feature that has been \
828+
deprecated due to lack of demand",
828829
cfg_fn!(no_debug))),
829830
("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
830831
"omit_gdb_pretty_printer_section",

src/test/compile-fail/feature-gate-no-debug.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010

1111
#![allow(deprecated)]
1212

13-
#[no_debug] //~ ERROR the `#[no_debug]` attribute is
13+
#[no_debug] //~ ERROR the `#[no_debug]` attribute was
1414
fn main() {}

src/test/compile-fail/issue-1962.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// compile-flags: -D while-true
1212
fn main() {
1313
let mut i = 0;
14-
while true { //~ ERROR denote infinite loops with loop
14+
while true { //~ ERROR denote infinite loops with `loop
1515
i += 1;
1616
if i == 5 { break; }
1717
}

src/test/ui/lint/suggestions.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
12+
#![feature(no_debug)]
13+
14+
#[no_debug] // should suggest removal of deprecated attribute
15+
fn main() {
16+
while true { // should suggest `loop`
17+
let mut a = (1); // should suggest no `mut`, no parens
18+
println!("{}", a);
19+
}
20+
}

src/test/ui/lint/suggestions.stderr

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
warning: unnecessary parentheses around assigned value
2+
--> $DIR/suggestions.rs:17:21
3+
|
4+
17 | let mut a = (1); // should suggest no `mut`, no parens
5+
| ^^^ help: remove these parentheses
6+
|
7+
= note: #[warn(unused_parens)] on by default
8+
9+
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
10+
--> $DIR/suggestions.rs:14:1
11+
|
12+
14 | #[no_debug] // should suggest removal of deprecated attribute
13+
| ^^^^^^^^^^^ help: remove this attribute
14+
|
15+
= note: #[warn(deprecated)] on by default
16+
17+
warning: denote infinite loops with `loop { ... }`
18+
--> $DIR/suggestions.rs:16:5
19+
|
20+
16 | while true { // should suggest `loop`
21+
| ^---------
22+
| |
23+
| _____help: use `loop`
24+
| |
25+
17 | | let mut a = (1); // should suggest no `mut`, no parens
26+
18 | | println!("{}", a);
27+
19 | | }
28+
| |_____^
29+
|
30+
= note: #[warn(while_true)] on by default
31+
32+
warning: variable does not need to be mutable
33+
--> $DIR/suggestions.rs:17:13
34+
|
35+
17 | let mut a = (1); // should suggest no `mut`, no parens
36+
| ---^^
37+
| |
38+
| help: remove this `mut`
39+
|
40+
note: lint level defined here
41+
--> $DIR/suggestions.rs:11:9
42+
|
43+
11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
44+
| ^^^^^^^^^^
45+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: --error-format json
12+
13+
// ignore-windows (see Issue #44968)
14+
15+
// The output for humans should just highlight the whole span without showing
16+
// the suggested replacement, but we also want to test that suggested
17+
// replacement only removes one set of parentheses, rather than naïvely
18+
// stripping away any starting or ending parenthesis characters—hence this
19+
// test of the JSON error format.
20+
21+
fn main() {
22+
// We want to suggest the properly-balanced expression `1 / (2 + 3)`, not
23+
// the malformed `1 / (2 + 3`
24+
let _a = (1 / (2 + 3));
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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}

src/test/ui/path-lookahead.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ warning: unnecessary parentheses around `return` value
22
--> $DIR/path-lookahead.rs:18:10
33
|
44
18 | return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
66
|
77
= note: #[warn(unused_parens)] on by default
88

0 commit comments

Comments
 (0)