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
This commit is contained in:
commit
e3fb84e951
@ -44,7 +44,7 @@ use std::collections::HashSet;
|
|||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
|
use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
|
||||||
use syntax_pos::{Span, SyntaxContext};
|
use syntax_pos::{BytePos, Span, SyntaxContext};
|
||||||
use syntax::symbol::keywords;
|
use syntax::symbol::keywords;
|
||||||
|
|
||||||
use rustc::hir::{self, PatKind};
|
use rustc::hir::{self, PatKind};
|
||||||
@ -153,7 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers {
|
|||||||
declare_lint! {
|
declare_lint! {
|
||||||
NON_SHORTHAND_FIELD_PATTERNS,
|
NON_SHORTHAND_FIELD_PATTERNS,
|
||||||
Warn,
|
Warn,
|
||||||
"using `Struct { x: x }` instead of `Struct { x }`"
|
"using `Struct { x: x }` instead of `Struct { x }` in a pattern"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -174,11 +174,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
|
|||||||
}
|
}
|
||||||
if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node {
|
if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node {
|
||||||
if ident.node == fieldpat.node.name {
|
if ident.node == fieldpat.node.name {
|
||||||
cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS,
|
let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
|
||||||
fieldpat.span,
|
fieldpat.span,
|
||||||
&format!("the `{}:` in this pattern is redundant and can \
|
&format!("the `{}:` in this pattern is redundant",
|
||||||
be removed",
|
ident.node));
|
||||||
ident.node))
|
let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':');
|
||||||
|
err.span_suggestion_short(subspan,
|
||||||
|
"remove this",
|
||||||
|
format!("{}", ident.node));
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -894,7 +898,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
|
|||||||
let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION,
|
let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION,
|
||||||
sp,
|
sp,
|
||||||
"function cannot return without recurring");
|
"function cannot return without recurring");
|
||||||
// FIXME #19668: these could be span_lint_note's instead of this manual guard.
|
|
||||||
// offer some help to the programmer.
|
// offer some help to the programmer.
|
||||||
for call in &self_call_spans {
|
for call in &self_call_spans {
|
||||||
db.span_note(*call, "recursive call site");
|
db.span_note(*call, "recursive call site");
|
||||||
@ -1130,35 +1133,55 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
|
|||||||
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
||||||
match it.node {
|
match it.node {
|
||||||
hir::ItemFn(.., ref generics, _) => {
|
hir::ItemFn(.., ref generics, _) => {
|
||||||
if attr::contains_name(&it.attrs, "no_mangle") &&
|
if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") {
|
||||||
!attr::contains_name(&it.attrs, "linkage") {
|
if attr::contains_name(&it.attrs, "linkage") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if !cx.access_levels.is_reachable(it.id) {
|
if !cx.access_levels.is_reachable(it.id) {
|
||||||
let msg = format!("function {} is marked #[no_mangle], but not exported",
|
let msg = "function is marked #[no_mangle], but not exported";
|
||||||
it.name);
|
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
|
||||||
cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
|
let insertion_span = it.span.with_hi(it.span.lo());
|
||||||
|
err.span_suggestion(insertion_span,
|
||||||
|
"try making it public",
|
||||||
|
"pub ".to_owned());
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
if generics.is_type_parameterized() {
|
if generics.is_type_parameterized() {
|
||||||
cx.span_lint(NO_MANGLE_GENERIC_ITEMS,
|
let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
|
||||||
it.span,
|
it.span,
|
||||||
"functions generic over types must be mangled");
|
"functions generic over \
|
||||||
|
types must be mangled");
|
||||||
|
err.span_suggestion_short(no_mangle_attr.span,
|
||||||
|
"remove this attribute",
|
||||||
|
"".to_owned());
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemStatic(..) => {
|
hir::ItemStatic(..) => {
|
||||||
if attr::contains_name(&it.attrs, "no_mangle") &&
|
if attr::contains_name(&it.attrs, "no_mangle") &&
|
||||||
!cx.access_levels.is_reachable(it.id) {
|
!cx.access_levels.is_reachable(it.id) {
|
||||||
let msg = format!("static {} is marked #[no_mangle], but not exported",
|
let msg = "static is marked #[no_mangle], but not exported";
|
||||||
it.name);
|
let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
|
||||||
cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);
|
let insertion_span = it.span.with_hi(it.span.lo());
|
||||||
|
err.span_suggestion(insertion_span,
|
||||||
|
"try making it public",
|
||||||
|
"pub ".to_owned());
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemConst(..) => {
|
hir::ItemConst(..) => {
|
||||||
if attr::contains_name(&it.attrs, "no_mangle") {
|
if attr::contains_name(&it.attrs, "no_mangle") {
|
||||||
// Const items do not refer to a particular location in memory, and therefore
|
// Const items do not refer to a particular location in memory, and therefore
|
||||||
// don't have anything to attach a symbol to
|
// don't have anything to attach a symbol to
|
||||||
let msg = "const items should never be #[no_mangle], consider instead using \
|
let msg = "const items should never be #[no_mangle]";
|
||||||
`pub static`";
|
let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
|
||||||
cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
|
// `const` is 5 chars
|
||||||
|
let const_span = it.span.with_hi(BytePos(it.span.lo().0 + 5));
|
||||||
|
err.span_suggestion(const_span,
|
||||||
|
"try a static value",
|
||||||
|
"pub static".to_owned());
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -471,6 +471,17 @@ impl CodeMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given a `Span`, try to get a shorter span ending just after the first
|
||||||
|
/// occurrence of `char` `c`.
|
||||||
|
pub fn span_through_char(&self, sp: Span, c: char) -> Span {
|
||||||
|
if let Ok(snippet) = self.span_to_snippet(sp) {
|
||||||
|
if let Some(offset) = snippet.find(c) {
|
||||||
|
return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sp
|
||||||
|
}
|
||||||
|
|
||||||
pub fn def_span(&self, sp: Span) -> Span {
|
pub fn def_span(&self, sp: Span) -> Span {
|
||||||
self.span_until_char(sp, '{')
|
self.span_until_char(sp, '{')
|
||||||
}
|
}
|
||||||
|
@ -424,7 +424,7 @@ mod no_mangle {
|
|||||||
mod inner { #![no_mangle="3500"] }
|
mod inner { #![no_mangle="3500"] }
|
||||||
|
|
||||||
#[no_mangle = "3500"] fn f() { }
|
#[no_mangle = "3500"] fn f() { }
|
||||||
//~^ WARN function f is marked #[no_mangle], but not exported
|
//~^ WARN function is marked #[no_mangle], but not exported
|
||||||
|
|
||||||
#[no_mangle = "3500"] struct S;
|
#[no_mangle = "3500"] struct S;
|
||||||
|
|
||||||
|
@ -10,9 +10,8 @@
|
|||||||
|
|
||||||
// compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics
|
// compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics
|
||||||
|
|
||||||
// FIXME(#19495) no_mangle'ing main ICE's.
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn foo() { //~ ERROR function foo is marked #[no_mangle], but not exported
|
fn foo() { //~ ERROR function is marked #[no_mangle], but not exported
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -31,7 +30,7 @@ pub static BAR: u64 = 1;
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
static PRIVATE_BAR: u64 = 1; //~ ERROR static PRIVATE_BAR is marked #[no_mangle], but not exported
|
static PRIVATE_BAR: u64 = 1; //~ ERROR static is marked #[no_mangle], but not exported
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -11,10 +11,27 @@
|
|||||||
#![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
|
#![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
|
||||||
#![feature(no_debug)]
|
#![feature(no_debug)]
|
||||||
|
|
||||||
|
#[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
|
||||||
|
#[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
|
||||||
|
|
||||||
|
#[no_mangle] // should suggest removal (generics can't be no-mangle)
|
||||||
|
pub fn defiant<T>(_t: T) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
fn rio_grande() {} // should suggest `pub`
|
||||||
|
|
||||||
|
struct Equinox {
|
||||||
|
warp_factor: f32,
|
||||||
|
}
|
||||||
|
|
||||||
#[no_debug] // should suggest removal of deprecated attribute
|
#[no_debug] // should suggest removal of deprecated attribute
|
||||||
fn main() {
|
fn main() {
|
||||||
while true { // should suggest `loop`
|
while true { // should suggest `loop`
|
||||||
let mut a = (1); // should suggest no `mut`, no parens
|
let mut a = (1); // should suggest no `mut`, no parens
|
||||||
|
let d = Equinox { warp_factor: 9.975 };
|
||||||
|
match d {
|
||||||
|
Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
|
||||||
|
}
|
||||||
println!("{}", a);
|
println!("{}", a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
warning: unnecessary parentheses around assigned value
|
warning: unnecessary parentheses around assigned value
|
||||||
--> $DIR/suggestions.rs:17:21
|
--> $DIR/suggestions.rs:30:21
|
||||||
|
|
|
|
||||||
17 | let mut a = (1); // should suggest no `mut`, no parens
|
30 | let mut a = (1); // should suggest no `mut`, no parens
|
||||||
| ^^^ help: remove these parentheses
|
| ^^^ help: remove these parentheses
|
||||||
|
|
|
|
||||||
= note: #[warn(unused_parens)] on by default
|
= 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
|
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
|
--> $DIR/suggestions.rs:27:1
|
||||||
|
|
|
|
||||||
14 | #[no_debug] // should suggest removal of deprecated attribute
|
27 | #[no_debug] // should suggest removal of deprecated attribute
|
||||||
| ^^^^^^^^^^^ help: remove this attribute
|
| ^^^^^^^^^^^ help: remove this attribute
|
||||||
|
|
|
|
||||||
= note: #[warn(deprecated)] on by default
|
= note: #[warn(deprecated)] on by default
|
||||||
|
|
||||||
warning: variable does not need to be mutable
|
warning: variable does not need to be mutable
|
||||||
--> $DIR/suggestions.rs:17:13
|
--> $DIR/suggestions.rs:30:13
|
||||||
|
|
|
|
||||||
17 | let mut a = (1); // should suggest no `mut`, no parens
|
30 | let mut a = (1); // should suggest no `mut`, no parens
|
||||||
| ---^^
|
| ---^^
|
||||||
| |
|
| |
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
@ -28,18 +28,73 @@ note: lint level defined here
|
|||||||
11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
|
11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
warning: denote infinite loops with `loop { ... }`
|
warning: static is marked #[no_mangle], but not exported
|
||||||
--> $DIR/suggestions.rs:16:5
|
--> $DIR/suggestions.rs:14:14
|
||||||
|
|
|
|
||||||
16 | while true { // should suggest `loop`
|
14 | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
|
||||||
|
| -^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try making it public: `pub `
|
||||||
|
|
|
||||||
|
= note: #[warn(private_no_mangle_statics)] on by default
|
||||||
|
|
||||||
|
error: const items should never be #[no_mangle]
|
||||||
|
--> $DIR/suggestions.rs:15:14
|
||||||
|
|
|
||||||
|
15 | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
|
||||||
|
| -----^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try a static value: `pub static`
|
||||||
|
|
|
||||||
|
= note: #[deny(no_mangle_const_items)] on by default
|
||||||
|
|
||||||
|
warning: functions generic over types must be mangled
|
||||||
|
--> $DIR/suggestions.rs:18:1
|
||||||
|
|
|
||||||
|
17 | #[no_mangle] // should suggest removal (generics can't be no-mangle)
|
||||||
|
| ------------ help: remove this attribute
|
||||||
|
18 | pub fn defiant<T>(_t: T) {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: #[warn(no_mangle_generic_items)] on by default
|
||||||
|
|
||||||
|
warning: function is marked #[no_mangle], but not exported
|
||||||
|
--> $DIR/suggestions.rs:21:1
|
||||||
|
|
|
||||||
|
21 | fn rio_grande() {} // should suggest `pub`
|
||||||
|
| -^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: try making it public: `pub `
|
||||||
|
|
|
||||||
|
= note: #[warn(private_no_mangle_fns)] on by default
|
||||||
|
|
||||||
|
warning: denote infinite loops with `loop { ... }`
|
||||||
|
--> $DIR/suggestions.rs:29:5
|
||||||
|
|
|
||||||
|
29 | while true { // should suggest `loop`
|
||||||
| ^---------
|
| ^---------
|
||||||
| |
|
| |
|
||||||
| _____help: use `loop`
|
| _____help: use `loop`
|
||||||
| |
|
| |
|
||||||
17 | | let mut a = (1); // should suggest no `mut`, no parens
|
30 | | let mut a = (1); // should suggest no `mut`, no parens
|
||||||
18 | | println!("{}", a);
|
31 | | let d = Equinox { warp_factor: 9.975 };
|
||||||
19 | | }
|
32 | | match d {
|
||||||
|
... |
|
||||||
|
35 | | println!("{}", a);
|
||||||
|
36 | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
= note: #[warn(while_true)] on by default
|
= note: #[warn(while_true)] on by default
|
||||||
|
|
||||||
|
warning: the `warp_factor:` in this pattern is redundant
|
||||||
|
--> $DIR/suggestions.rs:33:23
|
||||||
|
|
|
||||||
|
33 | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
|
||||||
|
| ------------^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| help: remove this
|
||||||
|
|
|
||||||
|
= note: #[warn(non_shorthand_field_patterns)] on by default
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user