Skip to content

Commit 395388b

Browse files
committed
Auto merge of #45232 - zackmdavis:moar_lint_suggestions, r=estebank
code suggestions for non-shorthand field pattern, no-mangle lints continuing in the spirit of #44942 ![moar_lint_suggestions](https://user-images.githubusercontent.com/1076988/31485011-3b20cc80-aee7-11e7-993d-81267ab77732.png) r? @estebank
2 parents b796087 + 8e6ed12 commit 395388b

File tree

6 files changed

+141
-36
lines changed

6 files changed

+141
-36
lines changed

src/librustc_lint/builtin.rs

+44-21
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use std::collections::HashSet;
4444
use syntax::ast;
4545
use syntax::attr;
4646
use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
47-
use syntax_pos::{Span, SyntaxContext};
47+
use syntax_pos::{BytePos, Span, SyntaxContext};
4848
use syntax::symbol::keywords;
4949

5050
use rustc::hir::{self, PatKind};
@@ -153,7 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers {
153153
declare_lint! {
154154
NON_SHORTHAND_FIELD_PATTERNS,
155155
Warn,
156-
"using `Struct { x: x }` instead of `Struct { x }`"
156+
"using `Struct { x: x }` instead of `Struct { x }` in a pattern"
157157
}
158158

159159
#[derive(Copy, Clone)]
@@ -174,11 +174,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
174174
}
175175
if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node {
176176
if ident.node == fieldpat.node.name {
177-
cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS,
177+
let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
178178
fieldpat.span,
179-
&format!("the `{}:` in this pattern is redundant and can \
180-
be removed",
181-
ident.node))
179+
&format!("the `{}:` in this pattern is redundant",
180+
ident.node));
181+
let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':');
182+
err.span_suggestion_short(subspan,
183+
"remove this",
184+
format!("{}", ident.node));
185+
err.emit();
182186
}
183187
}
184188
}
@@ -894,7 +898,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
894898
let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION,
895899
sp,
896900
"function cannot return without recurring");
897-
// FIXME #19668: these could be span_lint_note's instead of this manual guard.
898901
// offer some help to the programmer.
899902
for call in &self_call_spans {
900903
db.span_note(*call, "recursive call site");
@@ -1130,35 +1133,55 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
11301133
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
11311134
match it.node {
11321135
hir::ItemFn(.., ref generics, _) => {
1133-
if attr::contains_name(&it.attrs, "no_mangle") &&
1134-
!attr::contains_name(&it.attrs, "linkage") {
1136+
if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") {
1137+
if attr::contains_name(&it.attrs, "linkage") {
1138+
return;
1139+
}
11351140
if !cx.access_levels.is_reachable(it.id) {
1136-
let msg = format!("function {} is marked #[no_mangle], but not exported",
1137-
it.name);
1138-
cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
1141+
let msg = "function is marked #[no_mangle], but not exported";
1142+
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
1143+
let insertion_span = it.span.with_hi(it.span.lo());
1144+
err.span_suggestion(insertion_span,
1145+
"try making it public",
1146+
"pub ".to_owned());
1147+
err.emit();
11391148
}
11401149
if generics.is_type_parameterized() {
1141-
cx.span_lint(NO_MANGLE_GENERIC_ITEMS,
1142-
it.span,
1143-
"functions generic over types must be mangled");
1150+
let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
1151+
it.span,
1152+
"functions generic over \
1153+
types must be mangled");
1154+
err.span_suggestion_short(no_mangle_attr.span,
1155+
"remove this attribute",
1156+
"".to_owned());
1157+
err.emit();
11441158
}
11451159
}
11461160
}
11471161
hir::ItemStatic(..) => {
11481162
if attr::contains_name(&it.attrs, "no_mangle") &&
11491163
!cx.access_levels.is_reachable(it.id) {
1150-
let msg = format!("static {} is marked #[no_mangle], but not exported",
1151-
it.name);
1152-
cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);
1164+
let msg = "static is marked #[no_mangle], but not exported";
1165+
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
1166+
let insertion_span = it.span.with_hi(it.span.lo());
1167+
err.span_suggestion(insertion_span,
1168+
"try making it public",
1169+
"pub ".to_owned());
1170+
err.emit();
11531171
}
11541172
}
11551173
hir::ItemConst(..) => {
11561174
if attr::contains_name(&it.attrs, "no_mangle") {
11571175
// Const items do not refer to a particular location in memory, and therefore
11581176
// don't have anything to attach a symbol to
1159-
let msg = "const items should never be #[no_mangle], consider instead using \
1160-
`pub static`";
1161-
cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
1177+
let msg = "const items should never be #[no_mangle]";
1178+
let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
1179+
// `const` is 5 chars
1180+
let const_span = it.span.with_hi(BytePos(it.span.lo().0 + 5));
1181+
err.span_suggestion(const_span,
1182+
"try a static value",
1183+
"pub static".to_owned());
1184+
err.emit();
11621185
}
11631186
}
11641187
_ => {}

src/libsyntax/codemap.rs

+11
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,17 @@ impl CodeMap {
471471
}
472472
}
473473

474+
/// Given a `Span`, try to get a shorter span ending just after the first
475+
/// occurrence of `char` `c`.
476+
pub fn span_through_char(&self, sp: Span, c: char) -> Span {
477+
if let Ok(snippet) = self.span_to_snippet(sp) {
478+
if let Some(offset) = snippet.find(c) {
479+
return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
480+
}
481+
}
482+
sp
483+
}
484+
474485
pub fn def_span(&self, sp: Span) -> Span {
475486
self.span_until_char(sp, '{')
476487
}

src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ mod no_mangle {
424424
mod inner { #![no_mangle="3500"] }
425425

426426
#[no_mangle = "3500"] fn f() { }
427-
//~^ WARN function f is marked #[no_mangle], but not exported
427+
//~^ WARN function is marked #[no_mangle], but not exported
428428

429429
#[no_mangle = "3500"] struct S;
430430

src/test/compile-fail/lint-unexported-no-mangle.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010

1111
// compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics
1212

13-
// FIXME(#19495) no_mangle'ing main ICE's.
1413
#[no_mangle]
15-
fn foo() { //~ ERROR function foo is marked #[no_mangle], but not exported
14+
fn foo() { //~ ERROR function is marked #[no_mangle], but not exported
1615
}
1716

1817
#[allow(dead_code)]
@@ -31,7 +30,7 @@ pub static BAR: u64 = 1;
3130

3231
#[allow(dead_code)]
3332
#[no_mangle]
34-
static PRIVATE_BAR: u64 = 1; //~ ERROR static PRIVATE_BAR is marked #[no_mangle], but not exported
33+
static PRIVATE_BAR: u64 = 1; //~ ERROR static is marked #[no_mangle], but not exported
3534

3635

3736
fn main() {

src/test/ui/lint/suggestions.rs

+17
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,27 @@
1111
#![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
1212
#![feature(no_debug)]
1313

14+
#[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
15+
#[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
16+
17+
#[no_mangle] // should suggest removal (generics can't be no-mangle)
18+
pub fn defiant<T>(_t: T) {}
19+
20+
#[no_mangle]
21+
fn rio_grande() {} // should suggest `pub`
22+
23+
struct Equinox {
24+
warp_factor: f32,
25+
}
26+
1427
#[no_debug] // should suggest removal of deprecated attribute
1528
fn main() {
1629
while true { // should suggest `loop`
1730
let mut a = (1); // should suggest no `mut`, no parens
31+
let d = Equinox { warp_factor: 9.975 };
32+
match d {
33+
Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
34+
}
1835
println!("{}", a);
1936
}
2037
}

src/test/ui/lint/suggestions.stderr

+66-11
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
warning: unnecessary parentheses around assigned value
2-
--> $DIR/suggestions.rs:17:21
2+
--> $DIR/suggestions.rs:30:21
33
|
4-
17 | let mut a = (1); // should suggest no `mut`, no parens
4+
30 | let mut a = (1); // should suggest no `mut`, no parens
55
| ^^^ help: remove these parentheses
66
|
77
= note: #[warn(unused_parens)] on by default
88

99
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
10+
--> $DIR/suggestions.rs:27:1
1111
|
12-
14 | #[no_debug] // should suggest removal of deprecated attribute
12+
27 | #[no_debug] // should suggest removal of deprecated attribute
1313
| ^^^^^^^^^^^ help: remove this attribute
1414
|
1515
= note: #[warn(deprecated)] on by default
1616

1717
warning: variable does not need to be mutable
18-
--> $DIR/suggestions.rs:17:13
18+
--> $DIR/suggestions.rs:30:13
1919
|
20-
17 | let mut a = (1); // should suggest no `mut`, no parens
20+
30 | let mut a = (1); // should suggest no `mut`, no parens
2121
| ---^^
2222
| |
2323
| help: remove this `mut`
@@ -28,18 +28,73 @@ note: lint level defined here
2828
11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
2929
| ^^^^^^^^^^
3030

31+
warning: static is marked #[no_mangle], but not exported
32+
--> $DIR/suggestions.rs:14:14
33+
|
34+
14 | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
35+
| -^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
| |
37+
| help: try making it public: `pub `
38+
|
39+
= note: #[warn(private_no_mangle_statics)] on by default
40+
41+
error: const items should never be #[no_mangle]
42+
--> $DIR/suggestions.rs:15:14
43+
|
44+
15 | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
45+
| -----^^^^^^^^^^^^^^^^^^^^^^
46+
| |
47+
| help: try a static value: `pub static`
48+
|
49+
= note: #[deny(no_mangle_const_items)] on by default
50+
51+
warning: functions generic over types must be mangled
52+
--> $DIR/suggestions.rs:18:1
53+
|
54+
17 | #[no_mangle] // should suggest removal (generics can't be no-mangle)
55+
| ------------ help: remove this attribute
56+
18 | pub fn defiant<T>(_t: T) {}
57+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
58+
|
59+
= note: #[warn(no_mangle_generic_items)] on by default
60+
61+
warning: function is marked #[no_mangle], but not exported
62+
--> $DIR/suggestions.rs:21:1
63+
|
64+
21 | fn rio_grande() {} // should suggest `pub`
65+
| -^^^^^^^^^^^^^^^^^
66+
| |
67+
| help: try making it public: `pub `
68+
|
69+
= note: #[warn(private_no_mangle_fns)] on by default
70+
3171
warning: denote infinite loops with `loop { ... }`
32-
--> $DIR/suggestions.rs:16:5
72+
--> $DIR/suggestions.rs:29:5
3373
|
34-
16 | while true { // should suggest `loop`
74+
29 | while true { // should suggest `loop`
3575
| ^---------
3676
| |
3777
| _____help: use `loop`
3878
| |
39-
17 | | let mut a = (1); // should suggest no `mut`, no parens
40-
18 | | println!("{}", a);
41-
19 | | }
79+
30 | | let mut a = (1); // should suggest no `mut`, no parens
80+
31 | | let d = Equinox { warp_factor: 9.975 };
81+
32 | | match d {
82+
... |
83+
35 | | println!("{}", a);
84+
36 | | }
4285
| |_____^
4386
|
4487
= note: #[warn(while_true)] on by default
4588

89+
warning: the `warp_factor:` in this pattern is redundant
90+
--> $DIR/suggestions.rs:33:23
91+
|
92+
33 | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
93+
| ------------^^^^^^^^^^^^
94+
| |
95+
| help: remove this
96+
|
97+
= note: #[warn(non_shorthand_field_patterns)] on by default
98+
99+
error: aborting due to previous error
100+

0 commit comments

Comments
 (0)